gpt4 book ai didi

c++ - 通过类模板参数跨平台选择运算符重载

转载 作者:搜寻专家 更新时间:2023-10-31 01:34:14 25 4
gpt4 key购买 nike

我正在尝试编写一个模板化类,它本质上只是其他类型的包装器,以便能够轻松地观察值发生的事情——每次任何运算符、构造函数、析构函数等是叫。因此,我试图通过在任何具有 operator bool() 的类上调用 operator bool(),在任何没有 operator bool() 的类上调用 static_cast 来创建一个 operator bool()。如果有人试图转换为 bool,则不能执行任何一个的类只能编译失败。我还没有关注这部分,因为我被这个更简单的案例难住了。

它在 MSVC 2015 上编译并运行良好,但不会在 Clang (3.8.1) 或 GCC (6.2) 上编译。 GCC 和 Clang 都设置为 -std=c++1z

显示 GCC 和 Clang 错误的在线编译器链接:https://godbolt.org/g/v3B6TE

这是显示问题的精简版本:

#include <type_traits>
#include <utility>
#include <assert.h>

template <typename T>
struct Wrapper {
T val;

template<typename...Params>
Wrapper(Params&&...args): val(std::forward<Params>(args)...){}

/**
* \brief bool conversion operator
*/
template <typename = std::enable_if_t<std::is_fundamental<T>::value>>
operator bool() const {
return static_cast<bool>(val);
}

/**
* \brief bool conversion operator
*/
template <typename = std::enable_if_t<!std::is_fundamental<T>::value>, typename = void>
operator bool() const {
return val.operator bool();
}
};


struct HasOperatorBool {
mutable bool done{ false };

operator bool() const{
done = true;
return done;
}
};

int main(int argc, char** argv) {
Wrapper<HasOperatorBool> whob;
bool didIt = whob;
assert(didIt);

Wrapper<int> wi{1};
bool bi = wi;
assert(bi);

return 0;
}

clang 和 gcc 都在说 std::enable_if_t 没有 type:

海湾合作委员会:

In file included from /tmp/gcc-explorer-compiler116910-70-16kehep/example.cpp:1:
/usr/lib/gcc/x86_64-linux-gnu/5.4.1/../../../../include/c++/5.4.1/type_traits:2388:44: error: no type named 'type' in 'std::enable_if<false, void>'; 'enable_if' cannot be used to disable this declaration
using enable_if_t = typename enable_if<_Cond, _Tp>::type;
^~~~~
15 : note: in instantiation of template type alias 'enable_if_t' requested here
template <typename = std::enable_if_t<std::is_fundamental<T>::value>>
^
40 : note: in instantiation of template class 'Wrapper<HasOperatorBool>' requested here
Wrapper<HasOperatorBool> whob;
^
In file included from /tmp/gcc-explorer-compiler116910-70-16kehep/example.cpp:1:
/usr/lib/gcc/x86_64-linux-gnu/5.4.1/../../../../include/c++/5.4.1/type_traits:2388:44: error: no type named 'type' in 'std::enable_if<false, void>'; 'enable_if' cannot be used to disable this declaration
using enable_if_t = typename enable_if<_Cond, _Tp>::type;
^~~~~
2 errors generated.
Compiler exited with result code 1

clang :

In file included from /tmp/gcc-explorer-compiler116910-70-1nlkefa/example.cpp:1:0:
/opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/type_traits: In substitution of 'template<bool _Cond, class _Tp> using enable_if_t = typename std::enable_if::type [with bool _Cond = std::is_fundamental<HasOperatorBool>::value; _Tp = void]':
16 : required from 'struct Wrapper<HasOperatorBool>'
40 : required from here
/opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/type_traits:2512:61: error: no type named 'type' in 'struct std::enable_if<false, void>'
using enable_if_t = typename enable_if<_Cond, _Tp>::type;

我可能对此的替代方法感兴趣,但我对这不能与 3 个编译器中的 2 个一起工作的技术原因非常感兴趣。一个或多个编译器是错误的吗?有没有办法实现我想要的?

最佳答案

您实际上并不是在做 SFINAE。使用 std::enable_if<T> 时, T有问题的应该直接来自编译器试图实例化的模板( immediate-context )。但是因为 T是您的的模板参数,而不是方法,替换失败并给出硬错误而不是 SFINAE。我不确定 VS 的行为在这方面是否符合标准。

您想要的是引入一个默认为类模板参数的虚拟模板参数:

/**
* \brief bool conversion operator
*/
template <typename X = T, typename = std::enable_if_t<std::is_fundamental<X>::value>>
operator bool() const {
return static_cast<bool>(val);
}

/**
* \brief bool conversion operator
*/
template <typename X = T, typename = std::enable_if_t<!std::is_fundamental<X>::value>, typename = void>
operator bool() const {
return val.operator bool();
}

关于c++ - 通过类模板参数跨平台选择运算符重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39951731/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com