Pat*_*ryk 7 c++ lambda type-traits template-meta-programming c++11
拥有以下代码:
#include <iostream>
#include <type_traits>
template <typename F,
typename = typename std::enable_if<
std::is_function< F >::value
>::type>
int fun( F f ) // line 8
{
return f(3);
}
int l7(int x)
{
return x%7;
}
int main()
{
auto l = [](int x) -> int{
return x%7;
};
fun(l); // line 23
//fun(l7); this will also fail even though l7 is a regular function
std::cout << std::is_function<decltype(l7)>::value ; // prints 1
}
Run Code Online (Sandbox Code Playgroud)
我会收到以下错误:
main2.cpp: In function ‘int main()’:
main2.cpp:23:8: error: no matching function for call to ‘fun(main()::<lambda(int)>&)’
fun(l);
^
main2.cpp:8:5: note: candidate: template<class F, class> int fun(F)
int fun( F f )
^
main2.cpp:8:5: note: template argument deduction/substitution failed:
main2.cpp:5:11: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
typename = typename std::enable_if<
^
Run Code Online (Sandbox Code Playgroud)
当我注释掉std::enable_if模板参数时,它编译并运行就好了.为什么?
检查T是否为函数类型.类型
std::function,lambdas,具有重载operator()的类和指向函数的指针不计入函数类型.
这个答案解释了你还需要使用std::remove_pointer<F>::type类型,因为函数在传递值时转换为指向函数的指针.所以你的代码应该是这样的:
template <typename F,
typename = typename std::enable_if<
std::is_function<
typename std::remove_pointer<F>::type
>::value
>::type>
int fun( F f )
{
return f(3);
}
Run Code Online (Sandbox Code Playgroud)
解决此问题的另一种方法是编写更具体的类型特征.例如,这一个检查参数类型是否可转换并适用于任何可调用的东西.
#include <iostream>
#include <type_traits>
#include <utility>
#include <string>
template<class T, class...Args>
struct is_callable
{
template<class U> static auto test(U*p) -> decltype((*p)(std::declval<Args>()...), void(), std::true_type());
template<class U> static auto test(...) -> decltype(std::false_type());
static constexpr auto value = decltype(test<T>(nullptr))::value;
};
template<class T, class...Args>
static constexpr auto CallableWith = is_callable<T, Args...>::value;
template <typename F,
std::enable_if_t<
CallableWith<F, int>
>* = nullptr
>
int fun( F f ) // line 8
{
return f(3);
}
int l7(int x)
{
return x%7;
}
int main()
{
auto l = [](int x) -> int{
return x%7;
};
std::cout << "fun(l) returns " << fun(l) << std::endl;
std::cout << CallableWith<decltype(l7), int> << std::endl; // prints 1
std::cout << CallableWith<decltype(l7), float> << std::endl; // prints 1 because float converts to int
std::cout << CallableWith<decltype(l7), const std::string&> << std::endl; // prints 0
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1497 次 |
| 最近记录: |