Избегайте самого неприятного разбора

Как мне заставить компилятор создавать временные объекты, использовать для них конструктор по умолчанию, не определяя функцию?

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

Решение

Вы можете заключить один из ваших аргументов в дополнительные наборы скобок, чтобы он не анализировался как объявление функции:

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

Или даже лучше, если у вас есть доступ к компилятору C ++ 11, используйте инициализацию фигурных скобок:

A< B , C<B> > a0{ B() , C<B>() };
5

Другие решения

Два пути:

  1. Инициализация через назначение:

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

    Обратите внимание, что это меняет семантику, поскольку требует, чтобы конструктор копирования или перемещения был доступен для типа (даже если это будет исключено, поэтому сгенерированный код будет тем же).

  2. Используйте больше скобок вокруг хотя бы одного аргумента:

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

Либо работает. Я предпочитаю второй способ, но он может стать нечитаемым, и «лишние» скобки удивят людей, не знакомых с таким поведением.

5

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

Во внешних скобках каждый аргумент может быть только выражением, а не объявлением.

Вам на самом деле нужно это только для того, чтобы один аргументов, чтобы предотвратить синтаксический анализ всей строки в качестве выражения. Вы можете выбрать, какой, или просто сделать оба.

Не забудьте написать комментарий рядом с кодом, объясняющим, что есть веская причина для «лишних» скобок, иначе бог знает, что кто-то придет и удалит их когда-нибудь в «второстепенном» коммите VCS.

3
По вопросам рекламы [email protected]