[英]Why does my (C++) compiler want to instantiate my parameter pack class when using std::endl?
考虑以下短程序。
#include <iostream>
template< typename ... Ts >
class foobar
{
static_assert( sizeof...(Ts) > 0 );
};
template< typename ... Ts >
std::ostream& operator<<( std::ostream& o, const foobar< Ts... >& )
{
return o;
}
int main(void)
{
std::cout << "This has nothing to do with foobar" << std::endl;
}
当我们尝试编译它时,我们得到...
ted@tedscomputer:~/Projects/emptypack$ g++ -o emptypack main.cpp
main.cpp: In instantiation of ‘class foobar<>’:
main.cpp:17:63: required from here
main.cpp:6:34: error: static assertion failed
6 | static_assert( sizeof...(Ts) > 0 );
| ~~~~~~~~~~~~~~^~~
ted@tedscomputer:~/Projects/emptypack$
我知道std::endl
有点奇怪(以至于它实际上有自己的 StackOverflow 标签),但这里到底出了什么问题? 为什么编译器尝试用空类型参数实例化我完全不相关的 class,失败,然后生成错误?
也许更重要的是,每次我写一个带有参数包的 class 时,我是否必须确保它可以在没有类型参数的情况下被实例化,即使这没有任何意义 w.r.t。 程序逻辑,以防万一它在std::endl
的一英里以内?
@Artyer 发现了这个:
... [注 1:尾随模板参数包...未以其他方式推导的将被推导为模板 arguments 的空序列。 - 尾注]
通常,如果您只是将特定类型的 object 传递给第二个参数,则不满足条件:
::operator<<(std::cout, foobar<int>{}); // compiles
即使你传递一个不同类型的 object,条件仍然不满足:
// Causes `error: no matching function for call to 'operator<<'`,
// does NOT trigger the `static_assert`.
::operator<<(std::cout, 0);
我认为这是因为编译器确实试图从参数类型中推断出Ts...
但失败了。
如果我们将参数拼写为std::enable_if_t<true, const foobar<Ts...> &>
,则条件始终满足,因为不可能从中推断出Ts...
,编译器甚至不会尝试.
但是为什么在我们的案例中满足条件呢? 因为std::endl
作为 function 模板(未指定模板参数)没有类型,所以不可能从中推断出任何内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.