gpt4 book ai didi

c++ - 内仿函数概念或接口(interface)

转载 作者:行者123 更新时间:2023-11-30 03:36:07 26 4
gpt4 key购买 nike

从这里开始,(endo)仿函数是能够获取一个对象并将其转换为同一类型的另一个对象的东西。仿函数最简单的例子是恒等式:

struct Identity {
template <typename T>
T Apply(T x) {
return x
}
};

我需要一个标识通用仿函数的“仿函数类型”。我想做的是编写如下代码:

class Sum {
public:
Sum(Functor* f, Functor* g) :
f_(f),
g_(g) {}
template <typename T>
T Apply(T x) { return f_->Apply(x) + g_->Apply(x); }
private
Functor* f_;
Functor* g_;
};

我想到的第一个想法当然是使用虚拟类:

struct Functor {
template <typename T>
virtual T Apply(T x) = 0;
};

这种方法无法解决的问题是模板不能是虚拟的。

然后我尝试使用 C++ 概念。但是,如 Specifying a concept for a type that has a member function template using Concepts Lite 中所述和 C++ Concepts: Can I define a concept that is itself a template?不可能有一个“模板化概念”。

最后我偶然发现了How to achieve "virtual template function" in C++因此我想出了以下可能的实现方式:

struct Functor {
template <typename T>
T Apply(const T& x); // No more virtual!!!
};

// ... Identity and Sum declarations properly inheriting from Functor ...

template <typename T>
T Functor::Apply(T x) {
if (Identity* specialized =
dynamic_cast<Identity*>(this)) {
return specialized->Apply(x);
} else if (const Sum* specialized =
dynamic_cast<const Sum*>(this)) {
return specialized->Apply(x);
} else ...
}

尽管这是编译,但这不是最好的解决方案。主要问题是:性能和代码重复。性能问题来自这样一个事实,即每次在 Functor 上调用 Apply 时,必须解析 Functor::Apply 中的长 if 子句。这是一个大问题,因为 Functor 可以深度嵌套(因此调用 Apply 可能会导致多次调用 Functor::Apply)。 “代码重复”问题是不言而喻的,因为每次我想定义一个新的 Functor 时,我还必须修改 Functor::Apply 添加一个新的 if 子句。

我在这里想问的是,是否有合适(更清晰)的方法来定义 Functor 接口(interface)/概念,从而可以创建像 Sum 这样的类。接受 C++ 概念和繁重的模板元编程。

附注所有代码片段都特意保持尽可能简单。避免建议使用 class 而不是 struct 或添加 const 标识符或使用唯一指针,这不是这个问题的重点。

最佳答案

不幸的是,我能想到的大多数(最佳)解决方案都要求您采用一些相当复杂的方法。当然,这不一定是坏事,但是当您继续设计程序时,它会使事情变得困惑。出于这个原因,我可能会建议一些更直接的东西:

template <typename F, typename G>
class Sum {
public:
Sum(F& f, G& g) :
f_(f),
g_(g) {}
template <typename T>
inline T Apply(T x) { return f_.Apply(x) + g_.Apply(x); }
private:
F& f_;
G& g_;
};

/*
For every class like the above, you may want to define an
easy-to-use generating function to simplify instantiations:
*/
template <typename F, typename G>
inline Sum<F, G> MakeSum(F& f, G& g)
{
return Sum<F, G>(f, g);
}

#include <cmath>

struct SquareRoot {
template <typename T>
inline T Apply(T x)
{
return std::sqrt(x);
}
};

struct Triple {
template <typename T>
inline T Apply(T x)
{
return T(3) * x;
}
};

// Example:

#include <iostream>

int main(void)
{
using namespace std;
SquareRoot square_root;
Triple triple;
// For g++, don't forget to compile with -std=c++1z
auto sum = MakeSum(square_root, triple);
cout << sum.Apply(1024) << endl;
}

诚然,它不如其他技术强大,但它可能是一个很好的起点。

关于c++ - 内仿函数概念或接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40835599/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com