Before c++11, I used to write code like this:
// 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
}
But now, with move semantics, it may become interesting (at least in some cases) to allow my functions to take rvalue references as parameters and add these overloads:
void doThingsWithA(A&& a);
void doThingsWithB(B&& b);
void doThingsWithC(C&& c);
From what I gather, if I want to be able to call those overloads within my big function, I need to use perfect forwarding, which may look like this (it is a bit less readable, but I guess that it can be ok with a good naming convention for the template types):
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
}
My problem is this: doesn't that mean that if my small functions have other overloads, it will become possible to call the big one with parameters of types for which it was not intended?
I think that this may work to prevent this:
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
}
Though I am not sure if it is not too restrictive, as I have no idea of how it behaves if I try to call the big functions with types that are implicitly convertible to A,B or C...
But... even supposing this works, do I really have no other options? (I mean... it's not easy on the eyes)
static_assert
if that's easier on your eyes. – GrousedoThingsWithABC
... ducks – Teratology