I want to use type_traits to overload by shared_ptr or not.
struct A {
A(int i) : x(i) {}
int x;
};
int main()
{
A a{4};
auto b = std::make_shared<A>(7);
A& c = a;
A* d = b.get();
A* e = &a;
std::cout << getX(a) << std::endl;
std::cout << getX(b) << std::endl;
std::cout << getX(c) << std::endl;
std::cout << getX(d) << std::endl;
std::cout << getX(e) << std::endl;
return 0;
}
This is one solution but has the problem that the return type must be pre-defined.
template <typename T>
typename std::enable_if_t<!boost::has_dereference<T>::value, int> getX(T t)
{
return t.x;
}
template <typename T>
typename std::enable_if_t<boost::has_dereference<T>::value, int> getX(T t)
{
return t->x;
}
But using the method below, I can make the return type auto
but it kind of looks clunky.
template <typename T, typename std::enable_if_t<!boost::has_dereference<T>::value>* = nullptr>
auto getX(T t)
{
return t.x;
}
template <typename T, typename std::enable_if_t<boost::has_dereference<T>::value>* = nullptr>
auto getX(T t)
{
return t->x;
}
Is there a method to use the first type and still get return type auto
?
I do not want to specify the type of A::x
and so auto
return type would be best. The second type does that but feels a bit clunky.
Or is there a better way of doing this? Thanks.
If you just want to run a different line of code or two for different types then constexpr if lets you do that without having to use enable_if
and allows you to use automatic return type deduction. You can simplify getX
into
template <typename T>
auto getX(T t)
{
if constexpr (boost::has_dereference<T>::value)
return t->x;
else
return t.x;
}
and this works because the path that is not executed is discarded so at compile time only the true path compiled.