Edit: The answer I've marked below isn't 100% correct, that's actually in a comment: using TPtr = decltype(&std::declval<T&>());
I'm trying to use std::conditional<>
to get the type of &T
, where T
may have operator&()
, or not.
The simple solution is to not even try, instead specify another template argument:
struct Foo
{
int operator&() { return 314; }
};
struct Bar { };
template <typename T, typename TPtr = T*>
struct A
{
T& _t;
A(T& t) : _t(t) {}
TPtr data() {
return &_t;
}
};
where client code is then
Foo foo;
A<Foo, int> aFoo(foo);
int pFooData = aFoo.data();
Bar bar;
A<Bar> aBar(bar);
Bar* pBarData = aBar.data();
But what I'd rather write is something like:
template <typename T>
struct B
{
using TPtr = typename std::conditional<has_operator_address_of<T>::value, typename std::result_of<decltype(T::operator&)&()>::type, T*>::type;
T& _t;
B(T& t) : _t(t) {}
TPtr data() {
return &t;
}
};
where has_operator_address_of
is modeled after is_call_possible
. Client code is then
B<Foo> bFoo(foo); // no need to second template argument
pFooData = bFoo.data();
but then the class without operator&()
fails to compile:
B<Bar> bBar(bar);
pBarData = bBar.data();
It seems that conditional
wants to compile both template arguments, so compilation fails when T
doesn't have operator&()
. I've tried sprinkling std::enable_if
around, but to no avail.
You can use
decltype
anddeclval
, with a little hackery to force an lvalue to be passed to the&
operator (which is required):Start with
#include <utility>
and define the following helper function:Then:
(live demo)