In letzter Zeit habe ich eine Vorlagenfunktion geschrieben, um einige Code-Wiederholungen zu lösen. Es sieht aus wie das:
template<class T, class R, class... Args>
R call_or_throw(const std::weak_ptr<T>& ptr, const std::string& error, R (T::*fun)(Args...), Args... args) {
if (auto sp = ptr.lock())
{
return std::invoke(fun, *sp, args...);
}
else
{
throw std::runtime_error(error.c_str());
}
}
int main() {
auto a = std::make_shared<A>();
call_or_throw(std::weak_ptr<A>(a), "err", &A::foo, 1);
}
Dieser Code funktioniert perfekt und class A
sieht folgendermaßen aus:
class A {
public:
void foo(int x) {
}
};
Aber kompiliert nicht für einen wie diesen:
class A {
public:
void foo(const int& x) {
}
};
Warum ist es so (warum meine ich, warum der Typ nicht abgeleitet werden kann) und wie (wenn es überhaupt möglich ist) kann ich diesen Code mit Referenzen arbeiten lassen? Live Beispiel
Args&&...
undstd::forward
?Antworten:
Ihr Problem ist, dass Sie Konfliktabzüge haben für
Args
:R (T::*fun)(Args...)
Args... args
Ich schlage vor, allgemeineren Code (keine Duplikate zwischen
R (T::*fun)(Args...)
undconst-Version
R (T::*fun)(Args...) const
und andere Alternative) mit zu haben:quelle
Args
Typen können nicht sowohl alsconst&
(aus derfun
Parameterdeklaration) als auch als Nichtreferenz aus derargs
Deklaration abgeleitet werden. Eine einfache Lösung besteht darin, zwei separate Parameterpakete vom Vorlagentyp zu verwenden:Als Nachteil kann ich mir bei längerer Nutzung etwas längere Fehlermeldungen vorstellen.
quelle
Args&&... args
Beachten Sie, dass der
Args
Typ des Vorlagenparameters wieconst int&
beim 3. Funktionsargument&A::foo
und wieint
beim 4. Funktionsparameter abgeleitet wird1
. Sie stimmen nicht überein und führen dazu, dass der Abzug fehlschlägt.Sie können den 4. Parameter vom Abzug ausschließen , z
LEBEN
PS:
std::type_identity
wird seit C ++ 20 unterstützt; aber es ist ziemlich einfach, eine zu implementieren.quelle
Args&&...
dannstd::type_identity
den 3. Parameter wie setzenR (T::*fun)(std::type_identity_t<Args>...)
. LIVE und LIVE