Ich habe das folgende Snippet Beispielcode:C++: Vorlage Argument Abzug, wenn Template-Funktionen als Argument zu anderen Template-Funktionen vorbei
Die Idee ist, dass es eine Containerklasse, hier Box
genannt, und wir möchten Erstellen neuer Versionen dieses Containers durch mapping eine Funktion über seinen aktuellen Inhalt.
#include <iostream>
#include <tuple>
template <typename TContent>
class Box
{
TContent d_content;
public:
Box(TContent content)
:
d_content(content)
{}
TContent content() const
{
return d_content;
}
template <typename Function>
auto transform(Function fun) -> decltype(Box{fun(d_content)})
{
return Box{fun(d_content)};
};
};
template <typename TElem>
std::tuple<TElem, TElem> toTuple(TElem thing)
{
std::cout << "Transforming " << thing << "to tuple.\n";
return std::make_tuple(thing, thing);
}
int main() {
std::cout << "Hello World!\n";
Box<int> mybox{10};
Box<int> box2 = mybox.transform([](int content){ return content * 2;});
std::cout << "Transformed box: " << box2.content() << '\n';
Box<std::tuple<int, int>> box3 = mybox.transform(&toTuple); // <- Template argument deduction/substitution fails here!
std::cout << "Transformed box: " << std::get<0>(box3.content()) << '\n';
}
In Zeile 42, wo box3 erstellt wird, Template-Argument Abzug/Substitution fehlschlägt:
main.cpp: In function 'int main()':
main.cpp:42:60: error: no matching function for call to 'Box<int>::transform(<unresolved overloaded function type>)'
Box<std::tuple<int, int>> box3 = mybox.transform(&toTuple);
^
main.cpp:22:8: note: candidate: template<class Function> decltype (Box<TContent>{fun(((Box<TContent>*)this)->Box<TContent>::d_content)}) Box<TContent>::transform(Function) [with Function = Function; TContent = int]
auto transform(Function fun) -> decltype(Box{fun(d_content)})
^~~~~~~~~
main.cpp:22:8: note: template argument deduction/substitution failed:
main.cpp:42:60: note: couldn't deduce template parameter 'Function'
Box<std::tuple<int, int>> box3 = mybox.transform(&toTuple);
^
exit status 1
Dies scheint der Fall zu sein, wenn Sie versuchen, eine Template-Funktion (Funktion zu übergeben Vorlage?) zu einer Funktion, die selbst einen Template-Argumentparameter erwartet.
Der einzige Weg, dies zu vermeiden, den ich bis jetzt gefunden habe, besteht darin, alle Template-Funktionen in Lambdas oder andere, nicht-Template-Funktionen zu verpacken. Dies ist natürlich suboptimal, da es eine Menge Vortexen einführt.
Warum in diesem Fall versagt, Template-Argument Abzug und ist es eine Möglichkeit, den Code der Box
Klasse (und/oder seine transform
Elementfunktion) zu verändern, dass Abzug Template-Arguments tut Arbeit zu gewährleisten?
(Der angegebene Code ist C++ 11 als repl.it noch nicht C++ 14 unterstützen. Der Hauptunterschied in C++ 14 wäre, dass der hintere Rückgabetyp transform
weggelassen werden kann. Das Fehler, aber bleibt gleich ich bin glücklich, mit Lösungen, die (nur) arbeiten in C++ 14 als auch)
Vielen Dank. Aus irgendeinem Grund kompilieren C++ 11 und C++ 14 glücklich den illformed Dekltyp. Unabhängig davon, es in 'Box' würde es richtig machen, oder? –
Qqwy
Wie "toTuple" ist eine Funktionsvorlage, keine Funktion. Sie können es nicht an eine andere Funktionsvorlage übergeben, da es keinen Typ hat, es kann nicht abgeleitet werden. " -> Gibt es Fälle, in denen eine Funktionsvorlage an eine andere Funktionsvorlage übergeben wird, aus der sie abgeleitet werden könnte? – Qqwy
@Qqwy Ja, könnte man. Und nein, es gibt keine. – Barry