模板元编程与经典名称重载相结合
Template metaprogramming mixed with classic name overloading
我想制作一个简单的一次函数应用程序到多个变量的模板,它工作得很好,但我觉得不够满足。这是工作代码:
#include <iostream>
// generated for last (or the only) variable sent to apply_to_many template overload
template<class Fun, class Type>
void apply_to_many(Fun fun, Type& current)
{
current = fun(current);
}
// variadic template + variadic arguments, fun is applied to
// current variable, and template is generated for the rest
template<class Fun, class Type, class ...Types>
void apply_to_many(Fun fun, Type& current, Types&... other_variables)
{
current = fun(current);
if(sizeof...(other_variables) > 0)
apply_to_many(fun, other_variables...);
}
// simple function returning square of value
int square(int x)
{
return x*x;
}
int main()
{
// some ints
int a{3}, b{4}, c{5}, d{6}, e{7};
std::cout << a << '\t'
<< b << '\t'
<< c << '\t'
<< d << '\t'
<< e << std::endl;
apply_to_many(square, a, b, c, d, e);
std::cout << a << '\t'
<< b << '\t'
<< c << '\t'
<< d << '\t'
<< e << std::endl;
}
输出:
3 4 5 6 7
9 16 25 36 49
虽然a b c d e
可以是不同的类型,如int
、double
、complex<float>
,但这里应用的函数只针对int
s ,因此 int
s 的平方类似于 int
s,float
s 的平方类似于 int
s,complex<float>
es 的平方类似于 int
s。 .. 好吧,complex<float>
只是无法转换。重点是——最好使用为这些类型提供的经典重载,例如 std::sqrt
或 std::pow
。但显然我们不能在不显式选择一个重载的情况下将重载的名称传递给模板。
apply_to_many(std::sqrt, a, b, c, d, e); //error
据我所知,我们不能将模板函数作为参数发送(这会很棒,但可能很棘手)。我会接受任何东西,甚至宏。
您可以使用通用 lambda (C++14):
apply_to_many([](auto v) { return std::sqrt(v); }, a, b, c, d, e);
在 c++11 中,您必须以旧方式创建仿函数:
struct Sqrt
{
template <typename T>
auto operator()(T value) const
-> decltype(std::sqrt(value))
{
return std::sqrt(value);
}
};
以后
apply_to_many(Sqrt{}, a, b, c, d, e);
我想制作一个简单的一次函数应用程序到多个变量的模板,它工作得很好,但我觉得不够满足。这是工作代码:
#include <iostream>
// generated for last (or the only) variable sent to apply_to_many template overload
template<class Fun, class Type>
void apply_to_many(Fun fun, Type& current)
{
current = fun(current);
}
// variadic template + variadic arguments, fun is applied to
// current variable, and template is generated for the rest
template<class Fun, class Type, class ...Types>
void apply_to_many(Fun fun, Type& current, Types&... other_variables)
{
current = fun(current);
if(sizeof...(other_variables) > 0)
apply_to_many(fun, other_variables...);
}
// simple function returning square of value
int square(int x)
{
return x*x;
}
int main()
{
// some ints
int a{3}, b{4}, c{5}, d{6}, e{7};
std::cout << a << '\t'
<< b << '\t'
<< c << '\t'
<< d << '\t'
<< e << std::endl;
apply_to_many(square, a, b, c, d, e);
std::cout << a << '\t'
<< b << '\t'
<< c << '\t'
<< d << '\t'
<< e << std::endl;
}
输出:
3 4 5 6 7
9 16 25 36 49
虽然a b c d e
可以是不同的类型,如int
、double
、complex<float>
,但这里应用的函数只针对int
s ,因此 int
s 的平方类似于 int
s,float
s 的平方类似于 int
s,complex<float>
es 的平方类似于 int
s。 .. 好吧,complex<float>
只是无法转换。重点是——最好使用为这些类型提供的经典重载,例如 std::sqrt
或 std::pow
。但显然我们不能在不显式选择一个重载的情况下将重载的名称传递给模板。
apply_to_many(std::sqrt, a, b, c, d, e); //error
据我所知,我们不能将模板函数作为参数发送(这会很棒,但可能很棘手)。我会接受任何东西,甚至宏。
您可以使用通用 lambda (C++14):
apply_to_many([](auto v) { return std::sqrt(v); }, a, b, c, d, e);
在 c++11 中,您必须以旧方式创建仿函数:
struct Sqrt
{
template <typename T>
auto operator()(T value) const
-> decltype(std::sqrt(value))
{
return std::sqrt(value);
}
};
以后
apply_to_many(Sqrt{}, a, b, c, d, e);