Przed C++ 11, kiedyś napisać kod jak poniżej:Właściwe stosowanie uniwersalnych odniesień
// Small functions
void doThingsWithA(const A& a)
{
// do stuff
}
void doThingsWithB(const B& b)
{
// do stuff
}
void doThingsWithC(const C& c)
{
// do stuff
}
// Big function
void doThingsWithABC(const A& a, const B& b, const C& c)
{
// do stuff
doThingsWithA(a);
doThingsWithB(b);
doThingsWithC(c);
// do stuff
}
Ale teraz, z semantyką poruszać, może okazać się interesujące (przynajmniej w niektórych przypadkach), aby umożliwić mój funkcje wziąć referencje rvalue jako parametry i dodać te przeciążeń:
void doThingsWithA(A&& a);
void doThingsWithB(B&& b);
void doThingsWithC(C&& c);
Z czego wnoszę, jeśli chcę, aby móc nazwać tych przeciążeń w moim wielkim funkcji, trzeba użyć doskonałe przekazywanie, który może wyglądać to (jest to nieco mniej czytelne, ale myślę, że może być ok z dobrym nazewnictwem nia dla typów szablonu):
template<typename TplA, typename TplB, typename TplC>
void doThingsWithABC(TplA&& a, TplB&& b, TplC&& c)
{
// do stuff
doThingsWithA(std::forward<TplA>(a));
doThingsWithB(std::forward<TplB>(b));
doThingsWithC(std::forward<TplC>(c));
// do stuff
}
Mój problem jest taki: nie oznacza to, że jeśli moje małe funkcje mają inne przeciążeń, stanie się możliwe, aby wywołać wielki jeden z parametrów typów, dla których to było nie przeznaczone?
myślę, że to może działać, aby zapobiec tego:
template<typename TplA, typename TplB, typename TplC,
class = typename std::enable_if<std::is_same<A, std::decay<TplA>::type>::value>::type,
class = typename std::enable_if<std::is_same<B, std::decay<TplB>::type>::value>::type,
class = typename std::enable_if<std::is_same<C, std::decay<TplC>::type>::value>::type>
doThingsWithABC(TplA&& a, TplB&& b, TplC&& c)
{
// do stuff
doThingsWithA(std::forward<TplA>(a));
doThingsWithB(std::forward<TplB>(b));
doThingsWithC(std::forward<TplC>(c));
// do stuff
}
Chociaż nie jestem pewien, czy to nie jest zbyt restrykcyjne, ponieważ nie mam pojęcia, jak się zachowuje, gdy próbuję zadzwonić wielkie funkcje z typami, które są domyślnie wymienialne na A, B lub C ...
Ale ... nawet zakładając, że to działa, czy naprawdę nie mam innych opcji? (Mam na myśli ... to nie jest łatwe w oczach)
Możesz użyć 'static_assert', jeśli jest to łatwiejsze dla twoich oczu. –
Możesz użyć makra do wygenerowania wszystkich 8 wersji 'doThingsWithABC' ... * kaczek * – Brian