我编写了这个C ++ 11特征模板来检查类型是否完整:
template <typename...>
using void_t = void;
template <typename T, typename = void>
struct is_complete : std::false_type
{};
template <typename T>
struct is_complete<T, void_t<decltype(sizeof(T))>> : std::true_type
{};
并按照以下方式进行测试:
struct Complete {};
int main()
{
std::cout << is_complete<Complete>::value
<< is_complete<class Incomplete>::value
<< '\n';
}
我希望测试程序打印10
,这是我用clang 3.4编译它时得到的输出。但是,使用gcc 4.9进行编译时,会打印11
而不是错误地将class Incomplete
标识为已完成。
我不确定我的代码是否正确,但在我看来,即使它是错误的,它在两个编译器上也应该表现相同。
问题1: 我的代码是否正确?
问题2:我是否在其中一个编译器中发现了错误?
编辑:
我不是要求替换我的代码。我问的是gcc或clang中是否有错误,以及这个特定的构造是否正确。
答案 0 :(得分:28)
问题似乎与void_t
的定义有关。将其定义为
template<typename... Ts>
struct make_void { typedef void type;};
template<typename... Ts>
using void_t = typename make_void<Ts...>::type;
在两个编译器(Demo)上产生正确的结果(10
)。
我认为这与N3911第2.3节中提到的问题相同,该文件提出了void_t
和CWG issue 1558。从本质上讲,该标准尚不清楚别名模板特化中的未使用参数是否会导致替换失败或被忽略。委员会2014年11月会议通过的CWG问题的解决方案澄清了问题中void_t
的较短定义应该有效,GCC 5.0实施该决议。