Рассмотрим следующий код (вопрос следует ниже):
#include <iostream>
struct Type0
{
Type0(char* c)
{}
};
struct Type1
{
Type1(int* i=nullptr) : i_(i)
{}
Type1(const Type1& other) = default;
int* i_;
};
template <typename ...>
struct Composable;
template <typename T0, typename ... T>
struct Composable<T0, T...> : T0, Composable<T...>
{
Composable()
{
std::cout << "Default Invoked: " << sizeof...(T) << std::endl;
}
Composable(const Composable& other) = default;
template<typename Arg, typename ... Args>
Composable(Arg&& arg, Args&& ... args) :
T0(std::forward<Arg>(arg)), Composable<T...>(std::forward<Args>(args)...)
{
std::cout << "Non-default invoked: " << sizeof...(T) << std::endl;
}
};
template <>
struct Composable<>{};
int main()
{
int i=1;
char c='c';
auto comp = Composable<Type0, Type1>(&c, &i);
std::cout << comp.i_ << std::endl;
}
Вы можете найти живой код здесь .Этот код обладает интересным свойством: в зависимости от того, компилируете ли вы его с опцией --std=C++17
или --std=C++14
, поведение меняется (вы можете попробовать это по моей ссылке на живой код: отредактируйте параметр вызова g ++ --std
ввнизу слева).
С --std=c++14
вы получите следующий вывод:
Non-default invoked: 0
Non-default invoked: 1
Default Invoked: 0
Non-default invoked: 1
0x0
С --std=C++17
вместо этого вы получите:
Non-default invoked: 0
Non-default invoked: 1
0x7ffcdf02766c
Дляменя эта разница сбивает с толку.Кажется очевидным, что версия C ++ 17 работает правильно, а C ++ 14 - неправильно.Версия C ++ 14 вызывает конструктор по умолчанию как Composable
, так и (из него) Type1
(отсюда и последняя строка вывода 0x0
, так как Type1
предоставляет это как значение по умолчанию дляего i
параметр конструктора).Однако я не вижу места, где конструктор по умолчанию должен вызываться.
Более того, если я вообще закомментирую конструктор по умолчанию Composable
, версия C ++ 17 делает точно то же самое, что и раньше, тогда как версия C ++ 14 теперь не компилируется, жалуясь наотсутствие конструктора по умолчанию.Если была какая-либо надежда на то, что разница каким-то образом объясняется различным поведением оптимизации, этот факт наверняка убьет ее (надежда была в любом случае мала, поскольку наблюдаемая разница сохраняется на всех уровнях оптимизации, включая 0).
Кто-нибудь может объяснить эту разницу?Является ли поведение C ++ 14 ошибкой или каким-то предполагаемым поведением, которое я не понимаю?Если поведение C ++ 14 является правильным в правилах C ++ 14, может кто-нибудь объяснить, откуда поступают вызовы конструктора по умолчанию?