Как определить псевдоним типа типа? - PullRequest
2 голосов
/ 17 июня 2020

Я могу обнаружить член, используя следующую проверку шаблона:

template <typename T, typename = void>
struct hasMember : std::false_type {};
template <typename T>
struct hasMember<T, decltype((void)T::member, void())> : std::true_type {};

Например, для:

class Test{
public:
   int member;
   using sometype = size_t; 
}

Я мог бы сделать:

if constexpr(hasMember<Test>)
{
   //do something
}

Теперь предположим Мне нужен constexpr if, который сообщает мне, есть ли у класса определение using. То есть что-то, что могло бы обнаружить, что некоторый класс (например, test) имеет определение using некоторого типа. Т.е. что-то вроде

if constexpr(hasSomeType<Test>)
{
     //do something
} 

Возможно ли такое в c ++ 17? Как?

1 Ответ

4 голосов
/ 17 июня 2020

Это можно сделать, используя тот же метод, что и при обнаружении элементов данных. Вместо использования элемента данных просто используйте тип элемента и void_t:

template <typename T, typename = void>
struct hasSomeType : std::false_type {};

template <typename T>
struct hasSomeType<T, std::void_t<typename T::member_type>> : std::true_type {};

В качестве альтернативы вы можете использовать идиому обнаружения :

template<typename T>
using member_type_t = typename T::member_type;

Вы можно поместить туда любое выражение, используя decltype.

Затем используйте псевдоним для выполнения обнаружения:

if constexpr (is_detected<member_type_t, Test>) {
    // ...
}

Конечно, в C ++ 20 все это становится одним лайнером :

// requires a type
if constexpr (requires(Test) { typename Test::member_type; }) {

}

// requires a member
if constexpr (requires(Test t) { t.member; }) {

}

Живой пример

...