с 17 вычетом аргумента шаблона класса к вариативным шаблон


This question already has an answer here:

Для того, чтобы создать универсальный завод был поднят необходимость в управлении общих параметров создания.

Это первый шаг:

struct Foo {    int num_;    class FooKey {};public:        Foo(int num, FooKey) : num_(num) {}    static std::unique_ptr<Foo> create(int i) {        return std::make_unique<Foo>(i, FooKey());    }    int num() const { return num_; }};template<class Obj>class Factory {public:    template<typename... ObjParams>    auto createObj(ObjParams&&... objectCreationParams) {        // the use of C++17 std::invoke / std::apply is for conveniency        // it can be done in a more cumbersome way with C++11/C++14        return std::invoke(&Obj::create, objectCreationParams...);    }};int main() {    Factory<Foo> f;    auto fObj = f.createObj(7);    std::cout << fObj->num() << std::endl;}
'remember'

Но мы хотим, чтобы завод с параметрами создания.

Поэтому мы добавляем вариативная params и перейти к функции создания для фабрики:

template<class Obj, class... ObjParams>class Factory {    std::tuple<ObjParams...> _objectCreationParams;public:    Factory(ObjParams&& ... params) {        _objectCreationParams =             std::make_tuple<ObjParams...>(std::forward<ObjParams>(params)...);    }    auto createObj() {        return std::apply(&Obj::create, _objectCreationParams);    }};template<class Obj, class... ObjParams>Factory<Obj, ObjParams...> createFactory(ObjParams&&... objParams) {    return Factory<Obj, ObjParams...>{std::forward<ObjParams>(objParams)...};}int main() {    auto factory = createFactory<Foo>(7);    auto fObj = factory.createObj();    std::cout << fObj->num() << std::endl;}
C++17 class template argument deduction

Мы хотим заменить сейчас функция создания для завода , но это не скомпилируется (г 7.2.0). Я предполагаю, что я пропускаю что-то с C 17 Правил вычетом аргумента шаблона класса.

Любое предложение?

template<class Obj, class... ObjParams>class Factory {    // ...public:    template<class... ObjParams_>    Factory(ObjParams_&& ... params) {        _objectCreationParams =             std::make_tuple<ObjParams_...>(std::forward<ObjParams_>(params)...);    }    // ...};// user-defined deduction guide template<class Obj, class... ObjParams>Factory(ObjParams&& ... params) -> Factory<Obj, ObjParams...>;int main() {    Factory<Foo> f(7); // compilation error - candidate expects 0 arguments, 1 provided        // shouldn't it auto deduce <class... ObjParams> for Factory?    auto fObj = f.createObj();    std::cout << fObj->num() << std::endl;}

Редактировать:

Учитывая, что нет частичного шаблона класса дедукции аргументации предлагаются следующие:

template<class Obj>struct Factory {    template<class... ObjParams>    class WithParams {        std::tuple<ObjParams...> _objectCreationParams;    public:        WithParams(ObjParams&& ... params) {            _objectCreationParams =                 std::make_tuple<ObjParams...>(std::forward<ObjParams>(params)...);        }        auto createObj() {            return std::apply(&Obj::create, _objectCreationParams);        }    };    template<class... ObjParams>    auto createObj(ObjParams&& ... params) {        return std::invoke(&Obj::create, std::forward<ObjParams>(params)...);    }};int main() {    Factory<Foo>::WithParams f(7);    auto fObj = f.createObj();    std::cout << fObj->num() << std::endl;    Factory<Foo> f2;    auto fObj2 = f2.createObj(8);    std::cout << fObj2->num() << std::endl;}