具有可变参数模板包的类模板的输出运算符

Ori*_*ent 2 c++ templates operator-overloading variadic-templates c++11

我试着写一个模板类和输出操作符,如下所示:

#include <iostream>

namespace N
{

template< typename ...types >
struct X
{
    static_assert((sizeof...(types) != 0), "zero length");
    X() = default;
    X(X const &) = default;
    X(X &&) = default;
    template< typename ...args >
    //explicit // does not matter
    X(args &&...) { ; }
    int value = 10;
};

template< typename ...types >
std::ostream &
operator << (std::ostream & out, X< types... > const & x)
{
    return out << x.value;
}

} // namespace N

int main()
{
    using namespace N;
    X< float > /*const*/ x; // `const` does not matter
    std::cout << x << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

static_assert离子提出:

main.cpp:9:5: error: static_assert failed "zero length"
    static_assert((sizeof...(types) != 0), "zero length");
    ^             ~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:32:23: note: in instantiation of template class 'N::X<>' requested here
    std::cout << x << std::endl;
                      ^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

如果在全局中定义的类模板Xoperator <<重载namespace则全部相同.我发现,评论using namespace N;行和替换X< float >N::X< float >解决问题.

如何解释这种行为?原因是什么?

编辑:

我找到了解决方案:是如何operator <<重载模板的重载参数如下:

template< typename first, typename ...rest >
std::ostream &
operator << (std::ostream & out, X< first, rest... > const & x)
{
    return out << x.value;
}
Run Code Online (Sandbox Code Playgroud)

分割typename ..types之类的不nessesarily.而且,由于代码的极度膨胀作为后果,所以根本不可取.

Cub*_*bbi 5

一种简单的方法来重现您的问题:

int main()
{
    using namespace N;
    std::cout << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,候选人的功能是所有重载operator<<namespace std,所有成员的operator <<的距离std::ostream,和你的函数模板operator<<namespace N.

13.3.1/7:"候选者是一个函数模板,使用模板参数推导生成候选函数模板特化"

因此,在开始重载解析之前,X<types...> const&必须从中推导出std::endl,这是模板函数的地址.函数的地址是函数指针类型,匹配N::X<types...> const&指针类型的唯一方法是推导types...为空列表.

(当然替换失败,因为没有任何函数指针类型的隐式转换N::X<>,这会将过载安静地消除为不可行,但静态断言不是直接上下文并且是一个硬错误)

故事的寓意:使用指令是邪恶的.