6

如何让编译器创建临时对象,在它们上使用默认构造函数而不定义函数?

struct B {};
template<class T> struct C {};

template<class T,class T1>
struct A
{
  A(const T& t,const T1& t1): m_t(t),m_t1(t1)
  {
    std::cout << __PRETTY_FUNCTION__ << "\n";
  }

  T m_t;
  T1 m_t1;
};


int main() {
  A< B , C<B> > a0( B() , C<B>() );   // Function definition
  A< B , C<B> > a1( B b , C<B> c );   // dito, *at least A(const T& t,const T1& t1) not called
}
4

3 回答 3

6

您可以将其中一个参数包装在一组额外的括号中,以阻止它被解析为函数声明:

A< B , C<B> > a0( (B()) , C<B>() );

或者更好的是,如果您可以访问 C++11 编译器,请使用大括号初始化:

A< B , C<B> > a0{ B() , C<B>() };
于 2012-11-06T11:11:03.350 回答
5

两种方式:

  1. 通过赋值初始化:

    auto a0 = A<B, C<B>>(B(), C<B>());
    

    请注意,在 C++17 之前,这会更改语义,因为它要求该类型可以使用复制或移动构造函数(即使这将被省略,因此生成的代码是相同的)。

  2. 在至少一个参数周围使用更多括号:

    A<B, C<B>> a0((B()), C<B>());
    

要么工作。第二种方式可能不可读,“多余的”括号会让不熟悉这种行为的人感到惊讶。

于 2012-11-06T11:11:33.410 回答
3
A< B , C<B> > a0((B()), (C<B>()));
//               ^   ^  ^      ^

使用外括号,每个参数只能是表达式而不是声明。

实际上,您只需要其中一个参数是这种情况,以防止整行被解析为表达式。你可以选择哪个,或者两者都做。

不要忘记在代码旁边写注释,解释“额外”括号是有充分理由的,否则天知道有一天会有人出现并在“次要”VCS 提交中删除它们。

于 2012-11-06T11:10:10.357 回答