通过组合实现函子重载
Achieve functor overloading through composition
给定一些现有的函子:
struct incr {
int operator()(int x) const { return x + 1; }
};
struct rep_str {
std::string operator()(const std::string& s) const { return s + s; }
};
我想知道是否有可能实现这样的事情:
auto f = overload<incr, rep_str>();
f(1); // returns 2
f("hello"); // returns "hellohello"
多个重载可能如下所示:
auto f = overload<fa, fb, fc, ...>();
// or...
auto g = overload<fa, overload<fb, overload<fc, ...>>>();
我想也许将 SFINAE 与 std::result_of_t
或类似的东西一起使用,但还没有弄清楚如何。
你不需要任何太花哨的东西:只需从所有参数继承并使用 using-声明从基类引入operator()
。但是,在可变参数的情况下,你不能在 using-声明中使用包扩展,所以你必须使用递归方法,如下所示:
template <class... Ts>
struct overload {}; // only used for empty pack
template <class T>
struct overload<T> : private T {
using T::operator();
};
template <class T1, class T2, class... Ts>
struct overload<T1, T2, Ts...> : private T1, overload<T2, Ts...> {
using T1::operator();
using overload<T2, Ts...>::operator();
};
恕我直言,布莱恩的答案更好,但既然我努力了,这是我的:
#include <type_traits>
#include <utility>
template <typename... Fns>
struct overload;
template <typename Fn, typename... Fns>
struct overload<Fn, Fns...>
{
template <typename... T>
std::result_of_t<Fn(T...)> operator()(T && ... args) const {
return Fn()(std::forward<T>(args)...);
}
using next = overload<Fns...>;
template <typename... T>
std::result_of_t<next(T...)> operator()(T && ... args) const {
return next()(std::forward<T>(args)...);
}
};
这
可以使用模板专用化来完成:
#include <string>
#include <iostream>
template <typename...Args>
struct overload{
};
template <> struct overload<int>{
int operator()(int x) const { return x + 1; }
};
template <> struct overload< std::string>{
std::string operator()(const std::string& s) const { return s + s; }
};
template <typename...Args >
auto f(Args...arg){
overload<Args...> func;
return func(arg...);
}
int main()
{
std::cout << f(3) << std::endl << f(std::string("Hello"));
}
注:@Brian和@md5i两个答案比这更一般、更优雅、更完美、更好。
相关文章:
- 如何为我的类实现/重载二进制运算符
- 如何为非常量和常量重载实现一次成员函数?
- 基于 SFINAE 的特征实现问题与函数模板重载
- 在函数重载中将右值引用实现为参数
- 如何实现容器的重载和模板函数的迭代器?
- 我想知道我将如何实现 + 运算符重载.我已经从我上一个问题中计算出 += 运算符重载
- 给定一个类型为 Container:<T>:Iterator 的函数参数,如何为某些类型的 T 实现特定的重载?
- C++ I/O 流重载:如何实现同一标头中相同 4 个 I/O 函数的 3 个不同类的友元重载?
- C++头/实现文件中的默认和重载构造函数?
- 为模板类中的>>运算符和<<运算符实现重载
- 什么更有效率?在重载函数中或通过在基类函数中检查对象类型来实现
- 将多态性与运算符 + 重载模板化类结合使用.如何实现基类?
- 如何拆分标头和重载实现运算符
- 通过重载实现部分模板专用化
- 重载实现的虚拟函数
- C++ - 使用取消引用运算符重载实现图形节点的合并
- 为什么运算符重载实现中的两个 Static 对象在 c++ 中始终相等
- 通过运算符重载实现矩阵乘法
- 运算符重载实现:0xC0000005:读取位置存在访问冲突
- c++中迭代器的前缀和后缀自增操作符重载实现的区别