繁体   English   中英

为什么我的(C++)编译器在使用 std::endl 时想要实例化我的参数包 class?

[英]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 发现了这个:

[temp.arg.explicit]/4

... [注 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM