如何在 c++ 中推断列表末尾的模板参数
How can I deduce template parameters at the end of the list in c++?
我正在尝试编写一个基于三件事模板化的函数:
- 第一种类型。
- 第二种类型。
- 带有参数的函数 第一和第二类型。
代码如下所示:
#include <iostream>
#include <typeinfo>
using namespace std;
// Assume that this function is in a library. Can't be modified.
void bar(int x, int y) {
cout << x << endl;
cout << y << endl;
}
// My code is below:
template <typename Type1, typename Type2, void (*fn)(Type1, Type2)>
void foo(Type1 x1, Type2 x2) {
fn(x1,x2);
}
int main() {
foo<int, int, &bar>(1,2);
}
代码有效,但我不满意我的模板必须包含<int, int, &bar>
. 我希望编译器能弄清楚 bar int, int
作为参数并弄清楚。
我尝试先列出函数,然后列出类型,但在声明中,Type1
在函数原型中无法识别,因为它稍后在同一原型中定义。
有没有优雅的解决方案?
编辑:我绝对不想传递指向堆栈上bar
的指针。 我想在bar
上成为模板。 参数应该只是(1, 2)
.
编辑2:我的意思是我想写foo<&bar>(1,2)
。
这是我不将函数作为参数传递的解决方案:
void bar(int a, int b) {
cout << a << " " << b << endl;
}
template <class F, F *fn>
struct Foo {
template <class... Args>
static decltype(auto) foo(Args &&... args) {
return fn(std::forward<Args>(args)...);
}
};
int main() {
Foo<decltype(bar), bar>::foo(1, 2);
return 0;
}
正如你所看到的,你必须写两次bar
,一次是类型,一次是价值,但我认为这是一个小小的不便。
或者简单版本(如果你不能使用 c++11)
template <class F, F* fn>
struct Foo {
template <class T1, class T2>
static void foo(T1 t1, T2 t2) {
fn(t1, t2);
}
};
对于那些不介意将函数 obj 作为参数传递的人:
选项 1:
template <class T1, class T2>
void foo(T1 x1, T2 x2, void (*fn)(T1, T2)) {
fn(x1, x2);
}
foo(1, 2, bar);
选项 2:
template <class T1, class T2, class F = void(*)(T1, T2)>
void foo(T1 x1, T2 x2, F fn)) {
fn(x1, x2);
}
foo(1, 2, bar);
选项 3:
template <class T1, class T2, class F>
void foo(T1 x1, T2 x2, F fn)) {
fn(x1, x2);
}
foo(1, 2, bar);
选项 3b(实际交易):
template <class T1, class T2, class F>
void foo(T1 &&x1, T2 &&x2, F &&fn)) {
std::forward<F>(fn)(std::forward(x1), std::forward(x2));
}
foo(1, 2, bar);
选项4(真正的真实交易)(嗯..取决于你需要什么)
template <class F, class... Args>
decltype(auto) foo(F &&fn, Args &&... args) {
return std::forward<F>(fn)(std::forward<Args>(args)...);
}
您
甚至可以避免使用包含该值的临时struct
键入bar
两次。结构将被任何像样的编译器优化出来,并且bar
不会在堆栈上传递,尽管它作为参数传递给foo
:
template <typename Fn>
struct FooT {
Fn &fn;
FooT(Fn fn):fn(fn){}
operator Fn *() {return fn;}
};
template <typename Fn>
inline FooT<Fn> foo(Fn *fn) {return FooT<Fn>(fn);}
int main() {
foo(bar)(1,2);
}
注意:转换为Fn *
允许直接调用fn
,而无需参数转发。如果需要,也可以使用模板调用它operator ()
向其传递/转发参数,但这似乎更简单且有效。如果您需要在调用fn
之前或之后执行更多操作,则模板化实现可能很方便。我不是转发参数,只是传递它们,为了简单起见,如有必要,可以轻松更改:
template <typename Fn>
struct FooT {
Fn &fn;
FooT(Fn fn):fn(fn){}
template <typename Type1, typename Type2>
void operator ()(Type1 x1, Type2 x2) {
fn(x1,x2);
}
};
Visual Studio 2012 生成的代码,禁用了全程序优化,仅以内联方式展开 (/Ob1):
foo(bar)(1,2);
011E16F0 push 2
011E16F2 push 1
011E16F4 call bar (011E13D0h)
011E16F9 add esp,8
相关文章:
- 概念中的cv限定符需要表达式参数列表
- 在没有参数列表的情况下使用模板名称"Event"无效,模板问题
- 错误 没有与参数列表匹配的重载函数"getline"实例
- std::vector 没有重载函数的实例与参数列表匹配
- 模板参数列表中的 false 在模板初始化期间计算为什么?
- C++模板/别名 - 模板参数列表中参数 1 处的类型/值不匹配
- 构造函数/函数声明参数列表中的统一初始化
- 模板化检查是否存在带有参数列表的类成员函数?
- 如何将类成员方法的参数列表自动填充写入可变参数?
- 带有整数的变量参数列表
- 转发变量参数列表以模拟 std::thread
- 错误:"模板<类_Tp,类_Dp>类 std::unique_ptr"的模板参数列表中参数 1 的类型/值不匹配
- C++-将具有引用的长参数列表重构为结构
- 缺少别名模板C++参数列表
- C++如果两个模板函数都与参数列表匹配,将调用哪个模板
- "extern"声明以及带有和不带参数列表的类模板实例的后续定义
- 使用显式模板参数列表和 [temp.arg.explicit]/3 的函数调用的演绎失败
- 没有函数模板的实例与我不知道为什么的参数列表匹配
- 我可以使用宏自动构建参数列表吗?
- 类成员函数参数列表是否可以依赖于模板参数?