参数类型的编译时类型检测
Compile time type detection of parameter types
我知道几种方法来检测给定类是否具有具有指定签名的函数。我想要的是在编译时推断签名。考虑:
struct test_class
{
void test( int a );
void test( float b );
};
我可以使用 decltype 和 SFINAE 来检测指定 test(( 的存在,使用简单的语法(如 has_test<test_class,int>();
.然而,我想要的是像test_types<test_class>::types -> mpl::list< int, float >
这样的东西。有人知道该怎么做吗?要求是无法准备可检测类型的列表(因此它将检测任何test( T )
,而不仅仅是我们"注册"的那些。
如果你能负担得起装饰test()
重载,就像(我知道这很丑陋,也许你可以拿出更漂亮的东西(:
struct test_class
{
param<int> test( int a, param_id<0> ={} );
param<float> test( float a, param_id<1> ={} );
};
那么这样的事情应该可以工作(Godbolt一致性视图(:
template<typename T> struct param{ using type = T; };
template<int I> struct param_id{};
template<typename... T> struct type_list{};
struct anything{ template<typename T> operator T&&(); };
template<int I>
struct matcher
{
template<typename T, typename E = std::enable_if_t<std::is_same<T,param_id<I>>::value> >
operator T();
};
template<typename T,int I,typename = std::void_t<>,typename... Ts>
struct test_types_impl{ using type = type_list<Ts...>; };
template<typename T,int I,typename... Ts>
struct test_types_impl<T,I,std::void_t<decltype(std::declval<T>().test( anything{}, matcher<I>{} ))>,Ts...>:
test_types_impl<T,I+1,void,Ts...,typename decltype(std::declval<T>().test( anything{}, matcher<I>{} ))::type>
{
};
template<typename T>
struct test_types{ using type = typename test_types_impl<T,0>::type; };
struct test_class
{
param<int> test( int a, param_id<0> ={} );
param<float> test( float a, param_id<1> ={} );
};
static_assert( std::is_same_v<test_types<test_class>::type, type_list<int,float>> );
以上至少需要可移动构造的参数类型和 C++17(但我认为它也可以在 C++11 中工作,并且可以与任何类型的参数一起使用(。
如果您设法获得允许的参数类型集的总排序,则可以省略param_id
。也许,我们甚至可以以某种方式省略param<T>
,但不确定(等待此:)的OP反馈(
IIUC,您希望对类应用一些检查以列出类型并累积(?(结果。如果是这样,您可以使用代码,如下所示:
#include <boost/mpl/list.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/empty.hpp>
#include <boost/mpl/front.hpp>
#include <type_traits>
template <typename ClassT, typename ParamT>
struct check : public std::true_type
{
};
// template <typename ClassT>
// struct check<ClassT, double> : public std::false_type
// {
// };
template <typename ClassT, typename ParamList, bool list_empty>
struct apply;
template <typename ClassT, typename ParamList>
struct apply <ClassT, ParamList, true> : public std::true_type{};
template <typename ClassT, typename ParamList>
struct apply <ClassT, ParamList, false> :
public std::integral_constant<
bool,
apply<
ClassT,
typename boost::mpl::pop_front<ParamList>::type,
boost::mpl::empty<typename boost::mpl::pop_front<ParamList>::type>::value
>::value && check<ClassT, typename boost::mpl::front<ParamList>::type>::value>
{
};
class Test
{
};
#include <iostream>
int main(int , char ** ) {
std::cout << std::boolalpha << apply<Test, boost::mpl::list<int, float, double>, false>::value << std::endl;
return 0;
}
假设,您的自定义支票check
,给了std::true_type
或std::false_type
。如果取消注释double
的专业化,结果将从true
更改为false
。
相关文章:
- 如何检测 USRP USB 类型?
- 如何检测类型类型别名?
- 用于检测函数类型是否为否的特征
- 错误:在尝试检测 std::cout 是否<< t 时,功能强制转换为数组类型;有效
- 如何检测参数包中的uint8_t类型
- SFINAE - 检测类型 T 是指针、数组还是带有随机访问运算符的容器,以及给定的值类型
- 使用SFINAE来检测void返回类型函数的存在
- 如何为QImage检测足够的格式(数据类型)以消耗最少的RAM
- 有没有一种方法可以使用SFINAE来检测一个类型是否实现了给定的抽象基类
- C++模板可以检测特定类型的成员吗
- 检测习惯用语和默认参数类型匹配
- 使用"JSON for Modern C++"库检测整数不适合指定类型?
- SFINAE 检测是否定义了类型
- 检测类型是否为"mapping"
- 检测<T>某些非数字类型 T 的 std::numeric::type 的特化
- 类型检测:使用variadic参数正确实现计算平均值的函数
- 参数类型的编译时类型检测
- C++矩阵乘法类型检测
- 层次结构中的对象类型检测
- 泛型类型检测