我观看了Walter Brown在Cppcon14上关于现代模板编程(第一部分,第二部分)的演讲,他在演讲中展示了他的void_tSFINAE技术.
示例:
给定一个简单的变量模板,该模板计算void所有模板参数是否格式正确:
template< class ... > using void_t = void;
Run Code Online (Sandbox Code Playgroud)
以及检查是否存在名为member的成员变量的以下特征:
template< class , class = void >
struct has_member : std::false_type
{ };
// specialized as has_member< T , void > or discarded (sfinae)
template< class T >
struct has_member< T , void_t< decltype( T::member ) > > : std::true_type
{ };
Run Code Online (Sandbox Code Playgroud)
我试图理解为什么以及如何运作.因此一个小例子:
class A {
public:
int member;
};
class B {
};
static_assert( has_member< A …Run Code Online (Sandbox Code Playgroud) 给定一个lambda,是否可以找出它的参数类型和返回类型?如果有,怎么样?
基本上,我想要lambda_traits哪些可以用于以下方式:
auto lambda = [](int i) { return long(i*10); };
lambda_traits<decltype(lambda)>::param_type i; //i should be int
lambda_traits<decltype(lambda)>::return_type l; //l should be long
Run Code Online (Sandbox Code Playgroud)
背后的动机是我想lambda_traits在一个接受lambda作为参数的函数模板中使用,我需要知道它的参数类型和函数内部的返回类型:
template<typename TLambda>
void f(TLambda lambda)
{
typedef typename lambda_traits<TLambda>::param_type P;
typedef typename lambda_traits<TLambda>::return_type R;
std::function<R(P)> fun = lambda; //I want to do this!
//...
}
Run Code Online (Sandbox Code Playgroud)
目前,我们可以假设lambda只接受一个参数.
最初,我尝试使用std::function:
template<typename T>
A<T> f(std::function<bool(T)> fun)
{
return A<T>(fun);
}
f([](int){return true;}); //error
Run Code Online (Sandbox Code Playgroud)
但它显然会给出错误.所以我将其更改TLambda为函数模板的版本,并希望在函数std::function内部构造对象(如上所示).
我发现两个编译器(g ++ 4.5,VS2010 RC)之间存在一些不一致的方式,它们将lambdas与类模板的部分特化相匹配.我试图为lambdas实现类似boost :: function_types的东西以提取类型特征.请查看此内容以获取更多详
在g ++ 4.5中,operator()lambda 的类型看起来像一个独立函数(R(*)(...)),而在VS2010 RC中,它看起来像一个成员函数(R( C::*)(...)).所以问题是编译器编写者可以自由地解释他们想要的任何方式吗?如果没有,哪个编译器是正确的?请参阅以下详细信息.
template <typename T>
struct function_traits
: function_traits<decltype(&T::operator())>
{
// This generic template is instantiated on both the compilers as expected.
};
template <typename R, typename C>
struct function_traits<R (C::*)() const> { // inherits from this one on VS2010 RC
typedef R result_type;
};
template <typename R>
struct function_traits<R (*)()> { // inherits from this one on g++ 4.5
typedef R result_type;
};
int main(void) …Run Code Online (Sandbox Code Playgroud) 当T被double(float)const我得到这个错误,当我尝试使用function<T>.
implicit instantiation of undefined template 'std::function<double (float) const>'
Run Code Online (Sandbox Code Playgroud)
但是什么时候T可以double(float).我试图用它std:: remove_cv<T>::type来删除它const,但这不起作用.是的,我有#include<functional>.
所以我的主要问题是:如何修复此问题并删除,const以便我可以将此函数类型放入std:: function.
我在使用operator()lambdas方法时遇到过这个问题,但我认为这个问题通常是关于任何方法类型的,而不仅仅是对于lambdas
但我的第二个问题是:double(float)const甚至意味着什么?!! 我能够了解
double (ClassName::) (float) const
Run Code Online (Sandbox Code Playgroud)
因为这意味着成员函数无法修改其ClassName对象.当我将此类型放入模板中以删除类类型时,我得到的double(float)const是导致问题的.
template<typename>
struct DropClassType;
template<typename Sig, typename C>
struct DropClassType<Sig (C::*)> {
typedef Sig type_without_class;
};
Run Code Online (Sandbox Code Playgroud)
(clang 3.4.2.来自g ++ - 4.9.1的错误更加神秘,但基本相同)
我想创建一个模板类或函数,它接收 lambda,并将其内部放入 std::function<> Lambda 可以有任意数量的输入参数 [](int a, float b, ...) std:: function<> 应该对应于 lambda 的 operator() 的类型
template <typename T>
void getLambda(T t) {
// typedef lambda_traits::ret_type RetType; ??
// typedef lambda_traits::param_tuple --> somehow back to parameter pack Args...
std::function<RetType(Args...)> fun(t);
}
int main() {
int x = 0;
getLambda([&x](int a, float b, Person c){});
}
Run Code Online (Sandbox Code Playgroud)
所以我需要以某种方式提取返回类型和参数包
这里的答案建议在 lambda 的 :: operator() 上使用部分规范
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};
template <typename ClassType, typename ReturnType, typename... Args> …Run Code Online (Sandbox Code Playgroud)