为什么我不能专门化std :: tuple_element?

Jar*_*ock 4 clang libstdc++ c++11 libc++

以下程序尝试std::tuple_element为用户定义的类型提供特化foo.不幸的是,clang-3.5用libc ++拒绝它,但是使用其他编译器或使用其他标准库来clang-3.5接受程序.这是对的吗?如果不是,为什么不呢?

#include <utility>

struct foo {};

namespace std
{
    template<size_t, class> struct tuple_element;
    template<size_t i>
    struct tuple_element<i, foo> {};
}

int main()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译器输出:

$ clang-3.5 -std=c++11 -stdlib=libc++ -lc++ test.cpp
test.cpp:11:8: error: explicit specialization of non-template struct 'tuple_element'
struct tuple_element<i, foo> {};
       ^            ~~~~~~~~
1 error generated.

$ clang-3.5 -std=c++11 -lstdc++ test.cpp
(no error)

$ g++-4.9 -std=c++11 test.cpp
(no error)
Run Code Online (Sandbox Code Playgroud)

T.C*_*.C. 7

libc++实体实际上是std::__1::一个内联命名空间std.因此,您自己的前向声明template<size_t, class> struct tuple_element;实际上声明了一个不同的类模板,然后部分特化由于模糊而爆炸(尽管错误消息具有误导性).

删除前向声明,它应该工作.

  • [`17.6.4.2.1命名空间std [namespace.std]/1`](http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4527.pdf) - 你的代码添加了对`namespace std`的声明.因此行为是不确定的. (3认同)
  • @Yakk s/ill-formed/UB /,是迂腐的. (2认同)