Ðаn*_*Ðаn 8 c++ macros templates
这是试图摆脱宏的另一种情况.考虑
void f_(int i) { printf("f_(int)\t%d\n", i); }
void f_(int i, double x) { printf("f_(int, double)\t%d, %5.3f\n", i, x); }
void g_(int i) { printf("g_(int)\t%d\n", i); }
void g_(int i, double x) { printf("g_(int, double)\t%d, %5.3f\n", i, x); }
Run Code Online (Sandbox Code Playgroud)
(想象一下f_()从.foo文件中获取数据或使用硬编码的"虚拟"值,g_()对.bar执行相同操作.)可能有一个函数来决定调用哪个重载:
void f(int i, double d) { (i > 0) ? f_(i, d) : f_(i); }
Run Code Online (Sandbox Code Playgroud)
具有相同的逻辑重复g_():
void g(int i, double x) { (i > 0) ? g_(i, x) : g_(i); }
Run Code Online (Sandbox Code Playgroud)
使用宏可以轻松删除重复的代码:
#define h(i, x, func_) (i > 0) ? func_(i, x) : func_(i);
// ...
h(-1, 314.1, f_);
h(99, 314.1, f_);
h(-1, 314.1, g_);
h(99, 314.1, g_);
Run Code Online (Sandbox Code Playgroud)
但当然我们宁愿不在C++中使用宏."明显"的模板
template<typename T>
void h2(int i, double x, T t)
{
(i > 0) ? t(i, x) : t(i);
}
// ...
h2(-1, 314.1, f_);
Run Code Online (Sandbox Code Playgroud)
失败,因为编译器无法弄清楚f_()要使用的重载.
如何替换宏的功能h?
您可以使用可变参数lambda并让lambda调用您想要调用的函数.
template<typename T>
void h2(int i, double x, T t)
{
i > 0 ? t(i, x) : t(i);
}
int main()
{
h2(-1, 314.1, [](auto... args){ f_(args...); });
// ^^ change this to g_ if you want to use g_ instead of f_
}
Run Code Online (Sandbox Code Playgroud)
如果你不介意改变定义的中f_和g_,你可以这样做
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
auto f_ = overloaded(
[](int i) { printf("f_(int)\t%d\n", i); },
[](int i, double x) { printf("f_(int, double)\t%d, %5.3f\n", i, x); }
);
auto g_ = overloaded(
[](int i) { printf("g_(int)\t%d\n", i); },
[](int i, double x) { printf("g_(int, double)\t%d, %5.3f\n", i, x); }
);
Run Code Online (Sandbox Code Playgroud)
然后你的h模板正是你想要的
template<typename T>
void h(int i, double x, T t)
{
i > 0 ? t(i, x) : t(i);
}
Run Code Online (Sandbox Code Playgroud)
该overloaded模板无耻地从复制这个例子std::visit.
要使其适用于C++ 11,您必须调整overloaded模板并添加辅助函数以推断类型参数
template<class... Ts> struct overloads;
template<> struct overloads<>{};
template<class T, class... Ts> struct overloads<T, Ts...> : T, overloads<Ts...>
{
overloads(T t, Ts... ts) : T(t), overloads<Ts...>(ts...) {}
using T::operator();
};
template<class... Ts> overloads<Ts...> overloaded(Ts&&... ts)
{ return overloads<Ts...>(std::forward<Ts>(ts)...); }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
199 次 |
| 最近记录: |