【发布时间】:2014-06-19 00:17:39
【问题描述】:
在c++11之前,我曾经写过这样的代码:
// 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
}
但是现在,有了移动语义,允许我的函数将右值引用作为参数并添加这些重载可能会变得有趣(至少在某些情况下):
void doThingsWithA(A&& a);
void doThingsWithB(B&& b);
void doThingsWithC(C&& c);
据我所知,如果我希望能够在我的大函数中调用这些重载,我需要使用完美转发,它可能看起来像这样(它的可读性有点差,但我想它可以是好的,模板类型的命名约定很好):
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
}
我的问题是这样的:这是否意味着如果我的小函数有其他重载,就可以使用非预期类型的参数调用大函数?
我认为这可以防止这种情况发生:
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
}
虽然我不确定它是否过于严格,因为我不知道如果我尝试使用可隐式转换为 A、B 或 C 的类型调用大函数时它的行为...
但是……即使这样可行,我真的没有其他选择吗? (我的意思是......这对眼睛来说并不容易)
【问题讨论】:
-
您可以使用
static_assert,如果这对您来说更方便。 -
你可以使用宏来生成
doThingsWithABC的所有8个版本... ducks
标签: c++ c++11 perfect-forwarding universal-reference forwarding-reference