gpt4 book ai didi

c++ - 具有可变模板包的类模板的输出运算符

转载 作者:搜寻专家 更新时间:2023-10-31 00:35:41 25 4
gpt4 key购买 nike

我尝试编写一个模板类和输出运算符,如下所示:

#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提出的 ionic :

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.

如果类模板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;
}

拆分 typename ..types类(class)的不是nessesarily。此外,由于代码极度膨胀,这根本不可取。

最佳答案

重现问题的简单方法:

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

在这种情况下,候选函数都是 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<> 的隐式转换,这会以不可行的方式悄悄地消除重载,但静态断言不在直接上下文中并且是一个硬错误)

故事的寓意:using-directives 是邪恶的。

关于c++ - 具有可变模板包的类模板的输出运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23355117/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com