Ich schreibe eine Bibliothek mit vielen Funktionsobjekten, deren Klassen mehrere operator()
Überladungen haben, die nicht vom Zustand der Klassen abhängen und es nicht ändern. Nun habe ich versucht, meinen Code mit vielen alten APIs arbeiten zu lassen (es ist keine zufällige Notwendigkeit, ich musste mich tatsächlich mit solchen APIs auseinandersetzen) und beschloss daher, die Funktionsobjekte in einen Funktionszeiger umzuwandeln, der einem der beiden entspricht Überladungen. Irgendwann wurde mir klar, dass ich zu viele solcher Konvertierungen hatte, um Zeigeroperatoren zu funktionieren, und dass ich theoretisch in der Lage sein würde, einen einzigen variablen Konvertierungsoperator zu schreiben. Hier ist eine Klasse, eine solche variadische Betreiber Umsetzung:Variadic Funktionszeiger Umwandlung
struct foobar
{
template<typename... Args>
using fptr_t = void(*)(Args... args);
template<typename... Args>
operator fptr_t<Args...>() const
{
return [](Args... args) {
// Whatever
};
}
};
Wie Sie sehen können, habe ich die Lambda-Konvertierung verwendet Zeiger auf Funktion des Umwandlungsoperator zu implementieren, was aber kein Problem ist, da jede Funktion Objekt Ich habe staatenlos ist. Das Ziel war es, die Klasse wie folgt zu verwenden:
int main()
{
void(*foo)(int) = foobar();
void(*bar)(float, double) = foobar();
}
g ++ kein Problem hat, diesen Code mit der erwarteten Semantik kompilieren. Allerdings Klirren ++ rejects it mit einer Vorlage Substitution Fehlerfehler:
main.cpp:21:11: error: no viable conversion from 'foobar' to 'void (*)(int)' void(*foo)(int) = foobar(); ^ ~~~~~~~~ main.cpp:11:5: note: candidate function [with Args = int] operator fptr_t<Args...>() const ^ 1 error generated.
Beachten Sie, dass Klappern ++ hat kein Problem mit einer solchen Umwandlung Betreiber solange keine variadische Vorlagen beteiligt sind. Wenn ich einen einzelnen Template-Parameter verwende, hat er kein Problem, den Code zu kompilieren. Soll nun der obige Code vom Compiler akzeptiert oder abgelehnt werden?
ich dies die [wie diese gleichen Fehler] denken (https: // llvm.org/bugs/show_bug.cgi?id=24032). Es gibt auch eine verknüpfte SO-Frage. Richard Smith [sagt einen Fehler] (http://stackoverflow.com/questions/31225888/pre-typedefing-a-variadic-function-pointer-argument#comment50471304_31225888), also glaube ich ihm :). –
Workaround: konvertieren mit 'Vorlage Operator F *()', fügen Sie Sfinae Test, dass es ein Funktionstyp ist, extrahieren Args mit Traits, entpacken mit Hilfe, verwenden Sie Helfer, um Zeiger zu konvertieren? –
Yakk