标准是否要求std :: tuple_size是SFINAE友好的?

Han*_*ård 14 c++ sfinae c++14

编辑追加:问题标题是"做Visual Studio编译器或Clang有不正确的行为" - 但是已经改变了.

所以我在这里补充说clang和gcc按照我的意图编译它,但VS没有.

我有以下代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

我收到编译器错误:

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>          ]
Run Code Online (Sandbox Code Playgroud)

那是因为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.");   
};
Run Code Online (Sandbox Code Playgroud)

使替换失败成为一个严重的失败 - 制作SFINAE SFIAE

如果我删除

static_assert(_Always_false<_Tuple>::value, "The C++ Standard doesn't define tuple_size for this type.");
Run Code Online (Sandbox Code Playgroud)

有用.

代码是否扩展了c ++标准规则?或者微软是错的?

Rya*_*ing 6

N4140 20.4.1将tuple_size非专业版描述为:

template <class T> class tuple_size; // undefined
Run Code Online (Sandbox Code Playgroud)

通过提供定义,MSVC lib违反了该标准.

但是,您应该意识到,您的问题不是涉及所涉及的编译器,而是标准库实现.

  • @Hurkyl这是核心语言的术语,而不是我的术语.[temp.spec]/p4:"实例化的模板特化可以为给定的参数列表隐式实例化(14.7.1),也可以显式实例化(14.7.2).特化是一个类,函数或类成员,无论是实例化还是明确专业化(14.7.3)." (3认同)

Yak*_*ont 2

该标准要求tuple_size 支持 SFINAE 友好,但许多人认为这是一个缺陷,并且看起来有望在 C++17 中得到修复

要求所有专业化(在标准中指“模板实例化”)tuple_size基本上都是std::integral_constant<size_t, ?>它或继承自它。(它给编译器留下了一些自由)

如果未定义主模板,则不会违反这一点。但是,如果主模板被定义为空结构(或类似结构),则该空结构是一个模板实例(标准将其称为“专业化”),本质上不是std::integral_constant<size_t, ?>.

std::integral_constant<size_t, 42>根据我的阅读,主模板(“失败”情况)为或任何其他常量都是合法的。无用且邪恶,但合法。但作为一个空结构违反了标准。

然而,关于更改此设置以强制使用空结构的争论是关于措辞的,而不是关于这是否是一个好主意的。

感谢@TC,他在另一个答案的评论线程中解决了这个问题。