Определить, является ли тип std :: tuple?

В настоящее время у меня есть две функции:

template<typename Type> bool f(Type* x);
template<typename... List> bool f(std::tuple<List...>* x);

Есть ли способ объединить эти две функции с дополнительным параметром шаблона, который указывает, является ли передаваемый тип кортежем?

template<typename Type, bool IsTuple = /* SOMETHING */> bool f(Type* x);

12

Решение

Конечно, используя is_specialization_of (ссылка взята и исправлена ​​из Вот):

template<typename Type, bool IsTuple = is_specialization_of<Type, std::tuple>::value>
bool f(Type* x);

Вопрос, однако, действительно ли вы этого хотите? Обычно, если вам нужно знать, является ли тип кортежем, вам нужна специальная обработка для кортежей, и это обычно связано с аргументами шаблона. Таким образом, вы можете придерживаться вашей перегруженной версии.

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

template<class T>
bool f(T* x){
// common parts...
f_special_part(x);
// common parts...
}

с

template<class T>
void f_special_part(T* x){ /* general case */ }

template<class... Args>
void f_special_part(std::tuple<Args...>* x){ /* special tuple case */ }
13

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

Вы можете просто перенести свои функции на другую функцию:

template<typename Type,bool IsTuple> bool f(Type *x);

template<typename Type>
inline bool f(Type* x) { return f<Type,false>(x); }

template<typename... List>
inline bool f(std::tuple<List...>* x) { return f<std::tuple<List...>,true>(x); }
5

С C ++ 17 вот довольно простое решение, использующее if constexpr

template <typename> struct is_tuple: std::false_type {};

template <typename ...T> struct is_tuple<std::tuple<T...>>: std::true_type {};

Тогда вы можете сделать что-то вроде:

template<typename Type> bool f(Type* x) {
if constexpr (is_tuple<Type>::value) {
std::cout << "A tuple!!\n";
return true;
}

std::cout << "Not a tuple\n";
return false;
}

Тест, чтобы убедиться, что это сработало:

f(&some_tuple);
f(&some_object);

Выход:

Кортеж !!
Не кортеж


Решение взято частично из ответ нашел здесь: Как узнать, является ли тип специализацией std :: vector?

3

С C ++ 11 это мой предпочтительный шаблон:

// IsTuple<T>()
template <typename T>
struct IsTupleImpl : std::false_type {};

template <typename... U>
struct IsTupleImpl<std::tuple <U...>> : std::true_type {};

template <typename T>
constexpr bool IsTuple() {
return IsTupleImpl<decay_t<T>>::value;
}

Работает отлично. Нет зависимостей (я не могу использовать Boost).

3

Может быть, немного поздно, но вы также можете сделать что-то вроде этого, в более современном стиле c ++ 17 с переменными шаблона:

template <typename T>
constexpr bool IsTuple = false;
template<typename ... types>
constexpr bool IsTuple<std::tuple<types...>>   = true;

И некоторые тесты

struct TestStruct{};

static_assert(IsTuple<int> == false,                "Doesn't work with literal.");
static_assert(IsTuple<TestStruct> == false,         "Doesn't work with classes.");
static_assert(IsTuple<std::tuple<int, char>>,       "Doesn't work with plain tuple.");
static_assert(IsTuple<std::tuple<int&, char&>>,     "Doesn't work with lvalue references");
static_assert(IsTuple<std::tuple<int&&, char&&>>,   "Doesn't work with rvalue references");

Вы можете просмотреть это здесь https://godbolt.org/z/FYI1jS

РЕДАКТИРОВАТЬ:
Вы захотите запустить std :: decay, std :: remove_volatile, std :: remove_const для обработки особых случаев.

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