I have a function with these overloads:
A& f(B& b)
{
return b.a;
}
const A& f(const B& b)
{
return b.a;
}
The return statement can be a much more complicated logic which returns some value that is const if b
is const. For example, B
is a container of containers (possibly with even deeper nesting) and we are searching for one element. In this case, copying the function is not a good idea. Is there any alternatives for achieving the same result?
I can think of some solutions, but I don't really like them.
template <typename T>
auto f(T& b) -> decltype(b.a)
{
return b.a;
}
It works but becomes complicated if that b.a
is not so trivial (as in the with in the containers).
A& f(B& b)
{
return b.a;
}
const A& f(const B& b)
{
return f(const_cast<B&>(b));
}
This also works but if feels like a hack. Is there a simple and clean solution?
I would implement non-const version in terms of const version, not the other way round (as you did).
A& f(B& b)
{
return const_cast<A&>(f(static_cast<B const&>(b)));
}
It looks a bit safer from mutability point of view.
As for the template version, how about this:
template <typename T>
auto f(T& b) -> std::conditional_t<std::is_const<T>{}, A const&, A&>
{
return b.a;
}
If std::conditional_t
(C++14) is not supported, then use std::conditional
:
typename std::conditional<std::is_const<T>{}, A const&, A&>::type
Hope that helps.
A possible solution:
template<typename B>
struct Return_type { typedef A &Type; };
template<typename B>
struct Return_type<B const &> { typedef A const &Type; };
template<typename B>
typename Return_type<B>::Type f(B &&b)
{
return b.a;
}
EDIT:
C++14 will have function return type deduction, so this should work:
template<typename T>
auto &f(T &&b)
{
return b.a;
}
gcc 4.8.1 already compiles it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With