c++ - 在不创建参数对象的情况下解析 constexpr 函数

标签 c++ templates c++11 constexpr argument-dependent-lookup

简短版:

如果我有这样的功能:

constexpr bool has_some_property(Foo) { return true; }

有没有什么方法可以调用函数而不必实际实例化 Foo ?假设 Foo不是默认可构造的吗?

冗长的版本:

安东尼·威廉姆斯最近 wrote an article详细介绍了为任何 enum class 启用的一组免费功能专门化特定模板的对象。它遵循 <ios> 中的类似方案。 , std::is_error_code ,其中专门针对用户定义的类型或值的模板以允许 enable_if启用某些功能。以安东尼为例:

template<>
struct enable_bitmask_operators<my_bitmask>{
    static constexpr bool enable=true;
};

然后在定义运算符时:

template<typename E>
typename std::enable_if<enable_bitmask_operators<E>::enable,E>::type
operator|(E lhs,E rhs){

此技术的问题是模板特化必须与原始模板位于相同的命名空间中,因此这是行不通的:

namespace mystuff {
    enum class Foo {
        ...
    };

    // Fail: wrong namespace
    template<>
    struct enable_bitmask_operators<Foo> : std::true_type {}

另一种方法是使用 constexpr函数,可以在与类相同的命名空间中解析:

namespace mystuff {
    enum class Foo {
        ...
    };
    constexpr bool enable_bitmask_operators(Foo) { return true; }

然后在定义处:

template<typename E>
typename std::enable_if<enable_bitmask_operators(E()),E>::type
operator|(E lhs,E rhs){

这样做的好处是即使在嵌套类中也能很好地工作。它的问题是它需要一个默认的可构造类。这适用于我们的 enum class例如,但它不能作为特化问题的通用解决方案。因此,如果我们想象尝试使用 constexpr函数而不是其他类的模板特化我们可能会遇到其他失败:

struct Foo {
    Foo() = delete;
};
constexpr bool has_some_property(Foo) { return true; }

...

// Fail for Foo...use of deleted function
template<typename E>
typename std::enable_if<has_some_property(E()),E>::type doStuff() {}

这有点令人沮丧,因为我实际上并不需要创建该对象,我只是希望它在那里供 ADL 识别 constexpr函数来调用。我一直在想应该有某种方式可以说我想要那个功能而不必实际创建对象。我玩过std::declval但这在这种情况下不起作用。

有人知道解决这个难题的方法吗?

最佳答案

只是不要使用constexpr:

std::true_type has_some_property(Foo&& );

Foo 有吗?

using has_it = decltype(has_some_property(std::declval<Foo>()));
static_assert(has_it::value, "It should!");

这是一个未计算的上下文,所以我们永远不必调用任何 Foo 构造函数。并且可以回避 constexpr 需要常量表达式的问题。

关于c++ - 在不创建参数对象的情况下解析 constexpr 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28423742/

相关文章:

c++ - VS2013 因可变参数模板特化而失败

c++ - 递归函数周围的 lambda 包装器中的 this-pointer 捕获

c++ - 使用 UnhookWindowsHookEx() 解除 Hook 时,多个程序崩溃

c++ - 在 C/C++ 程序中,系统(Windows、Linux 和 Mac OS X)如何调用 main() 函数?

c++ - 我如何让 Anjuta 突出显示我的构建系统 (waf) 产生的错误/行?

C++获取模板中的类型名称

c++ - gcc 可以编译可变参数模板而 clang 不能

c++ - SDL2 窗口能否始终处于事件状态并位于 DirectX 窗口之上?

c++ - 模板元编程 : "does not have integral or enumeration type"

c++ - 为什么 tuple_size 是特征而不是成员