[英]How to create compile time check for multiple C++ types?
I have a template <class Class>
generic function that includes: 我有一个
template <class Class>
泛型函数,包括:
std::ostringsteam objectStream;
objectStream << std::forward<Class>(object);
return objectStream.str();
For efficiency, I wish to optimize the case of Class
strings. 为了提高效率,我希望优化
Class
字符串的大小写。
Therefore, I'm doing tags dispatch on templates for overloading the template function per item 27 is Scott Myers' Effective Modern C++ book. 因此,我正在为模板分配标签,以使每项27的模板功能过载,这是Scott Myers的《 Effective Modern C ++》一书。
Therefore I need to generate at compile time either a std::true_type
or std::false_type
. 因此,我需要在编译时生成
std::true_type
或std::false_type
。
Given a template<class Class>
, I need a std::true_type
if any of these expressions are true: 给定
template<class Class>
,如果以下任何表达式为真,则需要一个std::true_type
:
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 * >()
I'm not sure how to do the OR so the compiler can dispatch on the tags at compile time correctly. 我不确定如何执行“或”操作,以便编译器可以在编译时正确分派标签。
Related question, is there a way to drop the const
in a const char *
to make it char *
? 相关问题,是否有办法将
const
放入const char *
以使其成为char *
?
Therefore I need to generate at compile time either a
std::true_type
orstd::false_type
.因此,我需要在编译时生成
std::true_type
或std::false_type
。Given a
template<class Class>
, I need astd::true_type
if any of these expressions are true [...]给定一个
template<class Class>
,如果这些表达式中的任何一个为真,我就需要一个std::true_type
[...]
Remembering that std::true_type
and std::false_type
are alias, respectively, for 记住
std::true_type
和std::false_type
分别是别名
std::integral_constant<bool, true>; // aka std::true_type
std::integral_constant<bool, false>; // aka std::false_type
if I understand correctly, you want this or something similar 如果我理解正确,您想要这个或类似的东西
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>;
Related question, is there a way to drop the
const
in aconst char *
to make itchar *
?相关问题,是否有办法将
const
放入const char *
以使其成为char *
?
I suppose you can create a custom template as follows 我想您可以如下创建自定义模板
template <typename T>
struct foo
{ using type = T; };
template <typename T>
struct foo<T const *>
{ using type = T *; };
So you can simplify the preceding code as follows 这样您就可以简化前面的代码,如下所示
using 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>;
For your first question, 对于第一个问题,
If you're using c++17 you can do this in a few lines using a fold expression 如果您使用的是c ++ 17,则可以使用fold表达式在几行中完成此操作
#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;
}
For c++11 you can do something similar, but using recursion in place of the fold. 对于c ++ 11,您可以执行类似的操作,但是使用递归代替fold。
#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;
}
For your second question, if you want a general remove const on pointer to const T, you can use the built in type_traits and conditional, 对于第二个问题,如果要在指向const T的指针上常规删除const,则可以使用内置的type_traits和有条件的,
#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;
}
I like max66's answer. 我喜欢max66的答案。 Simple and elegant.
简洁大方。
If you need a more classic metafunction solution (ie something like check_type_t<T>
) and you don't want to use any meta-programming library like boost::mpl
or boost::hana
etc... You can simply do the following: 如果您需要更经典的元函数解决方案(例如,诸如
check_type_t<T>
类的东西),并且您不想使用诸如boost::mpl
或boost::hana
等之类的元编程库,则只需执行以下操作:
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, "");
C++ will try to select the most specialized template so when any of the type you want(for example string) is passed to Class
in check_type_t<>
then the C ++会尝试选择最专业的模板,以便在
check_type_t<>
中将check_type_t<>
任何类型(例如字符串)传递给Class
时,
std::enable_if_t<
std::is_same<typename std::decay<Class>::type, string>::value
>
is not ill formed and resulting to void
. 没有病态形成并导致
void
。 So this specialization is selected and the type inside is std::true_type
. 因此选择了此专业化,并且内部类型为
std::true_type
。 If none of the specializations is well formed then the main template is selected and the result is std::false_type
. 如果没有一个专业
std::false_type
良好,则选择主模板,结果为std::false_type
。
I hope it helped. 希望对您有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.