【发布时间】:2019-03-13 12:37:52
【问题描述】:
我正在尝试将this answer 中用于检测类是否具有成员变量x 的方法与this answer 结合使用,以根据使用enable_if 选择不同的实现。
基本上,我想编写一个 trait 类,给定类型 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;
}
g++ 给出的错误信息
error: 'x' is not a member of 'WithoutX'
struct HasX <T, decltype((void) T::x)> : std::true_type { };
在应该首先检测x 是否是成员的部分。奇怪的是,如果我取消注释倒数第二行实例化 HasX<WithoutX>::value 本身,g++ 编译没有错误 (Compiler Explorer)。
clang 和 msvc 在 Compiler Explorer 上编译都没有问题。
这里有什么问题?
【问题讨论】:
-
您可以使用:
std::void_t<decltype(T::x)>