标准要求std :: tuple_size是SFINAE友好的吗? [英] Does the standard require std::tuple_size to be SFINAE-friendly?
问题描述
编辑附件:
问题标题是做Visual Studio编译器或Clang有不正确的行为 - 但是已经更改。
Edit append: The question title was "do Visual Studio compiler or Clang have incorrect behavior"- but that have been changed.
这里的clang和gcc编译它的方式我打算,但VS不。
So I add here that clang and gcc compiles it the way I intended, but VS does not.
我有以下代码:
template<typename S, typename T, std::size_t... I>
void
print_tuple_like(S& s, const T& t, std::index_sequence<I...>)
{
void* unused[] = { &(s << std::get<I>(t))... };
}
template<typename S, typename T,
std::size_t N = std::tuple_size<decltype(T::children)>::value>
S& operator<<(S& s, const T& t)
{
print_tuple_like(s, t.children, std::make_index_sequence<N>{});
return s;
}
我收到一个编译错误:
1>c:\program files (x86)\microsoft visual studio 14.0\vc\include\utility(313): error C2338: The C++ Standard doesn't define tuple_size for this type.
1> c:\users\jonas\documents\visual studio 2015\projects\consoleapplication7\consoleapplication7\consoleapplication7.cpp(36): note: see reference to class template instantiation 'std::tuple_size<unknown-type>' being compiled
1> c:\users\jonas\documents\visual studio 2015\projects\consoleapplication7\consoleapplication7\consoleapplication7.cpp(43): note: see reference to function template instantiation 'void print_tuple_like<S,std::tuple<Signature::A,Signature::B>,0,1>(S &,const T &,std::integer_sequence<_Ty,0,1>)' being compiled
1> with
1> [
1> S=std::ostream,
1> T=std::tuple<Signature::A,Signature::B>,
1> _Ty=size_t
1> ]
1> c:\users\jonas\documents\visual studio 2015\projects\consoleapplication7\consoleapplication7\consoleapplication7.cpp(50): note: see reference to function template instantiation 'S &operator <<<std::ostream,Signature,2>(S &,const T &)' being compiled
1> with
1> [
1> S=std::ostream,
1> T=Signature
1> ]
这是因为visual studio中的以下代码:
That is because the following code in visual studio:
// TEMPLATE STRUCT tuple_size
template<class _Tuple>
struct tuple_size { // size of non-tuple
static_assert(_Always_false<_Tuple>::value, "The C++ Standard doesn't define tuple_size for this type.");
};
使替换失败成为一个硬故障 - 使SFINAE SFIAE
make the substitution failure into a hard failure- making the SFINAE SFIAE
如果我移除了
static_assert(_Always_false<_Tuple>::value, "The C++ Standard doesn't define tuple_size for this type.");
它可以工作。
纠正c ++标准规则?
或者是Microsoft错了?
Is the code strecthing the c++ standard rules? Or is Microsoft in the wrong?
推荐答案
tuple_size
不是SFINAE友好,但这是由很多都是缺陷,并且在C ++ 17中已经被修正。
The standard mandates that tuple_size
not be SFINAE friendly, but this is considered by many to be a defect, and looks on-track to be fixed in C++17.
需要所有的特殊化(在标准 - tuple_size
基本上是 std :: integral_constant< size_t,?>
它。 (它为编译器留下了一些自由)
It is required that all specializations (which in standard-speak for "template instantiations") of tuple_size
basically be std::integral_constant<size_t, ?>
or inherit from it. (It leaves some freedom to the compiler)
如果没有定义主模板,那么它不会违反。但是如果主模板被定义为一个空结构(或类似的),那么该空结构是一个模板实例(标准调用specialization),它本质上不是 std :: integral_constant< size_t,?>
。
If the primary template isn't defined, then it doesn't violate that. But if the primary template is defined to be an empty struct (or similar), then that empty struct is a template instance (which the standard calls a "specialization") that is not essentially std::integral_constant<size_t, ?>
.
根据我的阅读,主模板(失败 code> std :: integral_constant< size_t,42> 或任何其他常数。无用和邪恶,但法律。但是作为一个空的结构违反了标准。
By my reading, it would be legal for the primary template (the "failure" case) to be std::integral_constant<size_t, 42>
or any other constant. Useless and evil, but legal. But being an empty struct violates the standard.
然而,关于改变这个任务的空结构的论点是关于措辞,而不是如果这是一个好主意。
However, the arguments about changing this to mandate an empty struct are about wording, and not about if it is a good idea.
感谢@TC谁解决这个在另一个答案在这里的评论线程。
Thanks to @T.C. who solved this in a comment thread on another answer here.
这篇关于标准要求std :: tuple_size是SFINAE友好的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!