Во-первых, CTAD не выполняется при использовании оператора разрешения контекста, поэтому Foo::
никогда не может использоваться. Вы должны явно указать аргументы шаблона для этого Foo
.
Я предлагаю просто переместить Bar1
и Bar2
за пределы частичной специализации Foo
в область пространства имен и использовать
Foo{Bar1(1, 2.0, 3), Bar2(100, 23.4, 45)};
вместо.
Тогда вы получите ошибку, что вычет для Foo
не удастся. Это потому, что только конструкторы в первичном шаблоне рассматриваются для неявных руководств по выводам. Но конструктор, который вы хотите использовать, относится к частичной специализации, а не к первичному шаблону.
Поэтому вам нужно самостоятельно добавить соответствующее руководство по выводам, например:
template <typename... Args1, typename... Args2>
Foo(Bar1<Args1...>, Bar2<Args2...>) -> Foo<Typelist<Args1...>, Typelist<Args2...>>;
Тогда вы получите ошибку, что ни один конструктор не является жизнеспособным. Это связано с тем, что вы берете Bar1<Args1...>& b1
и Bar2<Args2...>& b2
в качестве не const
lvalue ссылок, но вы предоставляете их значения. Ссылки, отличные от const
lvalue, не могут быть привязаны к rvalues, поэтому вы получаете сообщение об ошибке. Либо принимайте параметры по значению, либо по const
lvalue reference.
Наконец, вы получите ошибку, что _b1
и _b2
не имеют конструкторов по умолчанию, что верно. Они необходимы, потому что вы инициализируете по умолчанию _b1
и _b2
в своем конструкторе. Вы только потом присваиваете им значения.
Так что либо добавьте конструкторы по умолчанию к Bar1
и Bar2
, либо лучше используйте инициализацию вместо присваивания:
Foo(const Bar1<Args1...>& b1, const Bar2<Args2...>& b2) : _b1(b1), _b2(b2) { }
После всех этих шагов код должен скомпилироваться. Я не уверен, что именно точно ваша цель, поэтому не совсем уверен, будет ли это делать то, что вы хотите.