如果作为参数传递的函子不带参数,则启用模板
Enable template if functor passed as argument takes no argument
我正在尝试为模板函数定义两个重载。 如果作为参数传递的函子没有参数,则生成第一个重载,否则将生成第二个重载。 我开始像这样实现:
template <typename R, typename... Types>
constexpr size_t argumentCount(R (*f)(Types...))
{
return sizeof...(Types);
}
template <typename Function>
typename std::enable_if<argumentCount<Function>() == 0, int>::value = 0 > callFunc(Function fu)
{
fu();
}
template <typename Function, typename... Params>
typename std::enable_if<argumentCount<Function>() == 0, int>::value = 0 > callFunc(Function fu, Params... params)
{
fu(std::forward<decltype(params)>(params)...);
}
由于多种原因(包括解析错误(,这不会编译。我想做的是,
callFunc([](){});
将调用重载 1,而callFunc([](int value1,int value2){});
将调用重载 2。
我怎样才能做到这一点?
您可以将检测习惯用语与std::void_t
和std::declval
一起使用来检测此类特征。
template <typename FuncT>
using invocable_without_args_t = std::void_t<decltype(std::declval<FuncT>()())>;
更多信息可以在这里找到;这篇文章帮助我理解了它是如何工作的。
如果可以添加间接级别...使用标签调度而不是 SFINAE 怎么样?
我的意思是,如下
#include <iostream>
#include <type_traits>
template <typename F>
void callFunc_helper (F fu, std::true_type)
{
std::cout << "zero version" << std::endl;
fu();
}
template <typename F, typename... Prs>
void callFunc_helper (F fu, std::false_type, Prs && ... params)
{
std::cout << "non zero version" << std::endl;
fu(std::forward<Prs>(params)...);
}
template <typename F, typename... Prs>
void callFunc (F fu, Prs && ... params)
{ callFunc_helper(fu, std::integral_constant<bool, 0u == sizeof...(Prs)>{},
std::forward<Prs>(params)...); }
int main ()
{
callFunc([]{});
callFunc([](int, int){}, 0, 1);
}
显然,如果您真的想检查函数参数的数量而不是以下参数的数量,您可以使用std::integral_constant<bool, 0u == argumentCount<Function>()>{}
(但为什么?
- 这是具有固定语法的版本:
template <typename R, typename... Types>
constexpr size_t argumentCount(R (*f)(Types...))
{
return sizeof...(Types);
}
template <typename Function>
typename std::enable_if<argumentCount<Function>() == 0, int> callFunc(Function fu)
{
fu();
}
template <typename Function, typename... Params>
typename std::enable_if<argumentCount<Function>() == 0, int> callFunc(Function fu, Params... params)
{
fu(std::forward<decltype(params)>(params)...);
}
- 在这个特定示例中,您不需要额外的重载,
Types...
可以为空。
template <typename Function, typename... Params>
auto callFunc(Function fu, Params... params)
{
fu(std::forward<decltype(params)>(params)...);
}
效果很好。
如果您需要两个模板函数,只需编写它们:
#include <iostream>
template <class R>
void callFunc(R (*f)()) {
std::cout << "Called no-arg templaten";
f();
}
template <class R, class T, class... Types, class... Params>
void callFunc(R (*f)(T, Types...), Params... params) {
std::cout << "Called multi-arg templaten";
f(params...);
}
void g() {
std::cout << "Called gn";
}
void h(int) {
std::cout << "Called hn";
}
int main() {
callFunc(g);
callFunc(h, 3);
return 0;
}
输出:
[temp]$ clang++ -std=c++11 test.cpp
[temp]$ ./a.out
Called no-arg template
Called g
Called multi-arg template
Called h
[temp]$
相关文章:
- 视觉工作室 2017;启用 /permissive 时,类型 "const wchar_t *" 的参数与类型 "PWSTR" 的参数不兼容
- 如何启用转换模板参数 T 以常量 T?
- SFINAE 和模板函数实例化:为什么在启用了 SFINAE 类型的函数参数中使用模板参数时无法推断模板参数?
- 如果作为参数传递的函子不带参数,则启用模板
- 如何使用布尔参数为按位运算符启用C++警告
- 如果每个参数都可以转换为特定类型,则启用 ctor
- 根据模板参数的默认值启用模板参数类型的自动扣除
- 如何在模板参数为bidirectional_iterator时启用模板类专用化
- 如何使用布尔模板参数启用成员函数?
- 如何仅在给定n个以上参数的情况下启用可变模板构造函数_if
- 不存在的标识符在非启用函数模板中用作默认参数
- 仅当参数可将某个类型的符号解释时,如何启用函数
- 'auto ... arg'的参数包形式在 lambda 中启用,但在函数中未启用?
- C++模板添加/启用基于模板参数的构造函数
- 根据模板参数启用模板 Ctor
- 启用从此可变参数模板共享
- 如何启用具有可变模板参数的类(_I)
- 只有模板参数有成员功能时,才启用成员功能
- 为什么 SFINAE 需要"启用"类模板参数?
- 如何在MSVC中为传递给变分函数的非POD参数启用警告/错误