2

我试着写一个模板类和输出运算符将其如下:与可变参数模板包类模板输出操作

#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; 
} 

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. 

如果类模板X和全局namespace中定义的operator <<重载全部相同。我发现,评论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; 
} 

类的分裂typename ..types不nessesarily。而且,由于代码的严重膨胀而导致后果并不理想。

+0

使用''\ n''而不是多余的'std :: endl'修复了它。 – Cubbi

回答

5

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

int main() 
{ 
    using namespace N; 
    std::cout << std::endl; 
} 

在这种情况下,候选人的功能是从namespace stdoperator<<所有重载,所有成员运营商< <的从std::ostream,并从namespace N你的函数模板operator<<

13.3.1/7:

所以,在重载决议可以开始,X<types...> const&必须从std::endl推断“如果候选人是一个函数模板,使用模板参数推导产生候选函数模板特”,这是一个模板函数的地址。函数的地址是函数指针类型,将N::X<types...> const&与指针类型匹配的唯一方法是将types...推导为空列表。因为不存在从任何函数指针类型到N::X<>的隐式转换,这将会消除静态过载,因为不可行,但静态断言不在紧接上下文中并且是硬错误)

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

+0

很好的解释。但是推断'types ...'为空列表还不够清楚。 – Orient

+0

如何将'N :: X < types... > const&'视为'decltype(std :: endl)'类型的指针? – Orient

+1

在这个答案中,将'template struct X'替换为'template struct X'应该解决这个问题。 – Orient