#c #c 17 #sfinae #typetraits
#c #c 17 #sfinae #typetraits
Вопрос:
В конкретном требовании мне нужно разрешить создание экземпляра функции шаблона func
только для определенного набора разрешенных типов.
Поэтому я попытался использовать уже доступный std::type_traits
, а затем использовать std::enable_if
для блокировки создания экземпляра. Вот моя реализация.
// C 17
#include <vector>
#include <cstdint>
#include <iostream>
#include <type_traits>
using my_int_t = std::int16_t; // T1
using my_string_t = std::string; // T2
using my_vec_t = std::vector<int>; // T3
// and so on .. a long list of types
/* Check input Type T : if it belongs to {T1,T2,T3}
If it belongs then only allow this version of func to instantiate
*/
template<typename T, typename T1,typename T2,typename T3>
using isCompatible = std::bool_constant<std::is_same_v<T,T1>
|| std::is_same_v<T,T2>
|| std::is_same_v<T,T3> >;
template<typename T>
using CompatibleTypeCheck = std::enable_if_t< isCompatible<std::remove_reference_t<T>,
my_int_t,
my_string_t,
my_vec_t>::value >;
template<typename T,
typename = CompatibleTypeCheck<T>>
void func(Tamp;amp; val) {
std::cout <<"Hello from Generic Func" << std::endl;
}
int main() {
// int z = 10;
// func(z); // Error ! as expected
my_int_t w = 100;
func(w); // OK
}
Но проблема в том, что слишком много разрешенных типов. Есть ли лучший способ очистить оба шаблона псевдонимов? т.е. isCompatible
и CompatibleTypeCheck
.
Если есть какой-либо лучший «идиоматический» способ достижения того же результата, пожалуйста, предложите его.
Ответ №1:
Вы можете написать isCompatible
так:
template<typename T, typename ...Ts>
using isCompatible = std::bool_constant<(std::is_same_v<T,Ts> || ...)>;
Вы мало что можете сделать CompatibleTypeCheck
, поскольку вам нужно где-то указать все разрешенные типы.
Вот демонстрация.
Обратите внимание, что enable_if
обычно используется, когда вы хотите включить или отключить определенные перегрузки. В вашем случае более простым способом было бы просто static_assert
внутри определения функции:
template<typename T>
void func(Tamp;amp; val) {
static_assert(isCompatible<std::remove_reference_t<T>,
my_int_t,
my_string_t,
my_vec_t>::value);
std::cout <<"Hello from Generic Func" << std::endl;
}
что позволяет полностью избежать необходимости CompatibleTypeCheck
.
Вот демонстрация.