J'ai une fonction générique template
qui inclut:
std::is_same<typename std::decay<Class>::type, char * >() std::is_same<typename std::decay<Class>::type, const char * >() std::is_same<typename std::decay<Class>::type, string >() std::is_same<typename std::decay<Class>::type, string * >() std::is_same<typename std::decay<Class>::type, const string * >()
Pour plus d'efficacité, je souhaite optimiser le cas de Class code> strings.
Par conséquent, je suis en train de distribuer des balises sur des modèles pour surcharger la fonction de modèle par élément 27 est le livre Effective Modern C ++ de Scott Myers.
Par conséquent, je dois générer au moment de la compilation, soit un std :: true_type
soit un std::false_type
.
Étant donné un template
, J'ai besoin d'un std :: true_type
si l'une de ces expressions est vraie:
std::ostringsteam objectStream; objectStream << std::forward<Class>(object); return objectStream.str();
Je ne sais pas comment faire le OU alors le le compilateur peut distribuer correctement les balises au moment de la compilation.
Question connexe, y a-t-il un moyen de déposer le const
dans un const char *
pour faire il char *
?
3 Réponses :
Par conséquent, je dois générer au moment de la compilation un
std :: true_type
oustd :: false_type
.Étant donné un
template
, j'ai besoin d'unstd :: true_type
si l'une de ces expressions est vraie [...]En se rappelant que
std :: true_type
etstd :: false_type
sont respectivement des alias pourusing tct = typename std::decay<Class>::type; // to make shorter using tft = typename foo<tct>::type using yourType = std::integral_constant<bool, std::is_same<tft, char * >::value || std::is_same<tft, string >::value || std::is_same<tft, string *>::value>;si Je comprends bien, vous voulez ceci ou quelque chose de similaire
template <typename T> struct foo { using type = T; }; template <typename T> struct foo<T const *> { using type = T *; };Question connexe, y a-t-il un moyen de déposer le
const
dans unconst char *
pour le rendrechar *
?Je suppose que vous pouvez créer un modèle personnalisé comme suit
using tct = typename std::decay<Class>::type; // to make shorter using yourType = std::integral_constant<bool, std::is_same<tct, char * >::value || std::is_same<tct, const char * >::value || std::is_same<tct, string >::value || std::is_same<tct, string *>::value || std::is_same<tct, const string *>::value>;Vous pouvez donc simplifier le code précédent comme suit
std::integral_constant<bool, true>; // aka std::true_type std::integral_constant<bool, false>; // aka std::false_type
J'aime la réponse de max66. Simple et élégant.
Si vous avez besoin d'une solution de métafonction plus classique (c'est-à-dire quelque chose comme check_type_t
) et que vous ne voulez pas utiliser de bibliothèque de méta-programmation comme boost: : mpl
ou boost :: hana
etc ... Vous pouvez simplement faire ce qui suit:
std::enable_if_t< std::is_same<typename std::decay<Class>::type, string>::value >
C ++ essaiera de sélectionner le le modèle le plus spécialisé, donc lorsque l'un des types que vous souhaitez (par exemple, une chaîne) est passé à Class
dans check_type_t
, alors le
template <class Class, class = void> struct check_type_ { using type = std::false_type; }; template <class Class> struct check_type_<Class, std::enable_if_t< std::is_same<typename std::decay<std::remove_const_t<Class>>::type, char*>::value >> { using type = std::true_type; }; template <class Class> struct check_type_<Class, std::enable_if_t< std::is_same<typename std::decay<std::remove_const_t<Class>>::type, string*>::value >> { using type = std::true_type; }; template <class Class> struct check_type_<Class, std::enable_if_t< std::is_same<typename std::decay<Class>::type, string>::value >> { using type = std::true_type; }; template <class Class> using check_type_t = typename check_type_<Class>::type; static_assert(std::is_same<check_type_t<char*>, std::true_type>::value, ""); static_assert(!std::is_same<check_type_t<int>, std::true_type>::value, "");
Pour votre première question,
Si vous utilisez c ++ 17, vous pouvez le faire en quelques lignes en utilisant une expression de repli
#include <iostream> #include <typeinfo> using namespace std; template <typename T> using remove_const_if_pointer_to_const = std::conditional_t<std::is_pointer<T>::value, std::add_pointer_t<std::remove_const_t<std::remove_pointer_t<T>>>, T>; int main() { using A = int; using B = int*; using C = const int*; std::cout << typeid(remove_const_if_pointer_to_const<A>).name() << std::endl; std::cout << typeid(remove_const_if_pointer_to_const<B>).name() << std::endl; std::cout << typeid(remove_const_if_pointer_to_const<C>).name() << std::endl; return 0; }
Pour c ++ 11, vous pouvez faire quelque chose de similaire, mais en utilisant la récursivité à la place de le pli.
#include <iostream> using namespace std; template<typename B, typename...Bs> struct any_true : std::conditional_t<bool(B::value), B, any_true<Bs...>>{}; template<typename B> struct any_true<B> : B {}; template <typename C, typename... Ts> using matches_my_types = any_true<std::is_same<C,Ts>...>; int main() { using Class = int; std::cout << matches_my_types<Class,bool,double,int>::value << std::endl; return 0; }
Pour votre deuxième question, si vous voulez une suppression générale de const sur le pointeur vers const T, vous pouvez utiliser le type_traits intégré et le conditionnel,
#include <iostream> using namespace std; template <typename C, typename... Ts> using matches_my_types = std::bool_constant< ( ... | std::is_same<C,Ts>::value)>; //or with a predefined set of types.. template <typename C> using matches_my_predefined_set_of_types = matches_my_types<C,bool,double,int>; int main() { using Class = int; std::cout << matches_my_types<Class,bool,double,int>::value << std::endl; std::cout << matches_my_predefined_set_of_types<Class>::value << std::endl; return 0; }