我正在尝试结合此答案中用于检测类是否具有成员变量的方法,x并根据此答案选择不同的实现enable_if。
基本上,我想编写一个trait类,给定一个type T,它可以访问成员(T::x如果存在),否则提供一个默认值。
以下代码无法在g ++上编译:(Compiler Explorer)
#include <iostream>
#include <type_traits>
// classes with / without x member
struct WithX { static constexpr int x = 42; };
struct WithoutX {};
// trait to detect x
template <typename T, typename = void>
struct HasX : std::false_type { };
template <typename T>
struct HasX <T, decltype((void) T::x)> : std::true_type { };
// trait to provide default for x
template <typename T>
struct FooTraits
{
template <bool enable = HasX<T>::value>
static constexpr std::enable_if_t< enable, size_t> x() { return T::x; }
template <bool enable = HasX<T>::value>
static constexpr std::enable_if_t<!enable, size_t> x() { return 1; }
};
int main() {
std::cout << HasX<WithX>::value << std::endl;
// Uncomment the following line to make this compile with g++
//std::cout << HasX<WithoutX>::value << std::endl;
std::cout << FooTraits<WithoutX>::x() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
g ++给出了错误消息
error: 'x' is not a member of 'WithoutX'
struct HasX <T, decltype((void) T::x)> : std::true_type { };
Run Code Online (Sandbox Code Playgroud)
首先应该检测x成员是否是成员。但是,奇怪的是,如果我取消注释它HasX<WithoutX>::value自己实例化的倒数第二行,则g ++编译时不会出错(Compiler Explorer)。
clang和msvc都可以在Compiler Explorer上编译而没有问题。
怎么了
事实上,切换评论:
//std::cout << HasX<WithoutX>::value << std::endl;
Run Code Online (Sandbox Code Playgroud)
确实是 gcc bug 的好兆头。
看来 gcc 对您的表单有问题:
template <typename T>
struct HasX <T, decltype((void) T::x)> : std::true_type {};
Run Code Online (Sandbox Code Playgroud)
更典型的方法是使用std::void_t:
template <typename T>
struct HasX <T, std::void_t<decltype(T::x)>> : std::true_type {};
Run Code Online (Sandbox Code Playgroud)
这确实解决了Demo 的问题。
| 归档时间: |
|
| 查看次数: |
134 次 |
| 最近记录: |