Получить тип & amp; для встроенного и оператора & ()?

Редактировать: Ответ, который я отметил ниже, не на 100% правильный, это на самом деле в комментарии: using TPtr = decltype(&std::declval<T&>());


Я пытаюсь использовать std::conditional<> чтобы получить тип &T, где T можно иметь operator&(), или нет.

Простое решение — даже не пытаться, вместо этого укажите другой аргумент шаблона:

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;
}
};

где код клиента тогда

Foo foo;
A<Foo, int> aFoo(foo);
int pFooData = aFoo.data();

Bar bar;
A<Bar> aBar(bar);
Bar* pBarData = aBar.data();

Но я бы предпочел написать что-то вроде:

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;
}
};

где has_operator_address_of моделируется после is_call_possible. Код клиента тогда

B<Foo> bFoo(foo); // no need to second template argument
pFooData = bFoo.data();

но тогда класс без operator&() не может скомпилировать:

B<Bar> bBar(bar);
pBarData = bBar.data();

Кажется, что conditional хочет скомпилировать оба аргумента шаблона, поэтому при сбое компиляции T не имеет operator&(), Я пробовал посыпать std::enable_if вокруг, но безрезультатно.

1

Решение

Ты можешь использовать decltype а также declval, с небольшим количеством взлома, чтобы заставить именующий быть переданным в & оператор (который требуется):

Начать с #include <utility> и определите следующую вспомогательную функцию:

template <typename T>
T& as_lvalue(T&& val)
{
return val;
}

Затем:

using TPtr = decltype(&as_lvalue(std::declval<T>()));

(живое демо)

1

Другие решения


По вопросам рекламы [email protected]