Parameterpack im Konstruktor von template
-
Ich habe ein template, welches gewissermaßen als Factory für T dient. Desweiteren möchte ich die Konstruktor-Parameter für T speichern.
(Stark reduziertes Minimalbeispiel)
template <class T, class... Args> class FooBar { public: FooBar( const std::string &, Args ... a_ ) : a(std::forward<Args>( a_ )...) {} virtual ~FooBar() = default; private: std::tuple<Args...> a; };
Aufruf:
FooBar<int> f( "x", 1, 1, "x" );
Beim Aufruf bekomme ich den Fehler:
no matching function for call to 'FooBar<int>::FooBar(const char [2], int, int, const char [2])
candidate: 'FooBar<T, Args>::FooBar(const string&, Args ...) [with T = int; Args = {}; std::string = std::__cxx11::basic_string<char>]'Sobald ich aber das T aus dem Template entferne, akzeptiert er das Konstrukt wieder, dabei hat T aktuell gar keinen Einfluss auf die Klasse selbst, da es nicht benutzt wird.
Nur ohne T macht die Klasse eben keinen Sinn mehr.Hat hier jemand eine Idee, woran das liegen könnte?
-
Der compiler den rest nicht mehr deduzieren, wenn der typ für "T" angegeben wird.
Was funktioniert ist folgendes:FooBar<int, int, int, std::string> f( "x", 1, 1, "x" );
Man muss in dem falle alle typen angeben.
Meine kurze suche hat ergeben, dass eine partielle "Class Template Argument Deduction" (CTAD) wohl aktuell nicht spezifiziert ist
-
Ich meine mich zu erinnnern, mal ein solches Konstrukt hinbekommen zu haben, kann aber aktuell nicht herausfinden, was in dem Fall genau anders war...
-
Ich kann nur zwei nicht besonders hübsche Workarounds anbieten.
1:
template <class T> struct FooBar { template <class... Args> class Impl { }; }; FooBar<int>::Impl f("x", 1, 1, "x");
2:
template <class T> struct Type {}; template <class T, class... Args> class FooBar { public: FooBar(Type<T>, const std::string &, Args ... a_ ) : a(std::forward<Args>( a_ )...) {} virtual ~FooBar() = default; private: std::tuple<Args...> a; }; FooBar f{Type<int>{}, "a", 1, 2, 3, 4};