我一直在试用Curiously Recurring Template Pattern以获得一个通用的单参数仿函数,并且有两个实现:一个使用模板模板参数,第二个尝试访问在接口类中派生的Functor :: type。在后者的示例中,编译器(gcc 5.4.0)报告CTRP派生类中没有类型命名为'type'
错误:无类型命名为 '结构立方<双>'
template<class T, template<class> class Functor>
class FunctorInterface_1 {
private:
const Functor<T> &f_cref;
public:
FunctorInterface_1() : f_cref(static_cast<const Functor<T>&>(*this)) {}
T operator() (T val) const { return f_cref(val); }
}; // FunctorInterface_1 (works)
template<class Functor>
class FunctorInterface_2 {
private:
const Functor &f_cref;
public:
using Ftype = typename Functor::type;
FunctorInterface_2() : f_cref(static_cast<const Functor&>(*this)) {}
Ftype operator() (Ftype val) const { return f_cref(val); }
}; // FunctorInterface_2 (no type in Functor!)
I '类型'然后尝试在以下两个类的main()中使用T = double进行编译:
template<class T>
struct Square : public FunctorInterface_1<T,Square> {
T operator()(T val) const { return val*val; }
}; // Square
template<class T>
struct Cube : public FunctorInterface_2<Cube<T>> {
using type = T;
T operator() (T val) const { return val*val*val; }
}; // Cube
可以将FunctorInterface_2/Cube示例修改为可用,或者 在第一个示例中是否需要在T上将接口类模板化为 ?谢谢!
编辑:使用gcc -std = C++ 14,但我可以通过在FunctorInterface_1 :: operator()中使用自动返回和参数类型来获得第二个示例来编译并运行 ,类型不是C++ 14标准的一部分。
编辑2:嗯,我感觉有点厚。我只是意识到我可以在一个新参数上为FunctorInterface_1 :: operator()创建模板,然而,对于我所考虑的应用程序,我真的很希望我的基类能够访问派生类中定义的类型。
这是一个相当花哨的替代方法,直接将此类型作为OP在第一次执行时作为模板参数提供。我必须提到,如果type通过trait传递,那么派生类也必须从trait中提取它,也就是'using type = T;'应该是'使用type = FunctorTraits> :: type;'。否则,这种实施是非常脆弱的。 –
VTT
Traits方法对保持我的接口不可知是有吸引力的,但是,它似乎会增加开发派生类型的负担。我想到的应用程序涉及复杂的抽象矢量操作,它将有一些用于索引的OrdinalType和用于包含在其中的数据的一些ElementType。我也在探索一种纯粹的特质方法(而不是继承),但是我们正在探索我们目前实现的虚拟继承(copius动态向下转换!)方法的优点。 –
@VTT,特征方法还有其他好处。例如。 Functor类不需要是类模板,就像OP使用的第一种方法一样。我同意第二点。然而,OP可能根本不需要它。 –