如何将模板参数传递给CRTP
How do I pass template parameters to a CRTP?
在以下代码中:
template <typename T>
class CRTP
{
public:
};
template <int I, typename T>
class CRTPInt
{
public:
};
template <template <typename> class T>
class Derived : public T<Derived<T>>
{
public:
};
void main()
{
Derived<CRTP> foo;
Derived<CRTPInt<2>> foo2;
}
我如何编写CRPTInt,以便传入一个模板化的参数,然后在派生定义中继续该参数?
谢谢,
Jim
CRTP模式通常用于启用静态多态性和混合(参数化)行为的能力。为了说明两种替代方案,可以方便地首先定义一个通用模板
template
<
typename Derived
>
class enable_down_cast
{
private:
// typedefs
typedef enable_down_cast Base;
public:
Derived const* self() const
{
// casting "down" the inheritance hierarchy
return static_cast<Derived const*>(this);
}
// write the non-const version in terms of the const version
// Effective C++ 3rd ed., Item 3 (p. 24-25)
Derived* self()
{
return const_cast<Derived*>(static_cast<Base const*>(this)->self());
}
protected:
// disable deletion of Derived* through Base*
// enable deletion of Base* through Derived*
~enable_down_cast() = default; // C++11 only, use ~enable_down_cast() {} in C++98
};
然后为您想要的行为类型定义一个接口类模板
template<typename FX>
class FooInterface
:
// enable static polymorphism
public enable_down_cast< FX >
{
private:
// dependent name now in scope
using enable_down_cast< FX >::self;
public:
// interface
void foo() { self()->do_foo(); }
protected:
// disable deletion of Derived* through Base*
// enable deletion of Base* through Derived*
~IFooInterface() = default; // C++11 only, use ~IFooInterface() {} in C++98/03
};
要获得该接口的不同实现,只需定义不同的类,每个类都从FooInterface
派生,并将其自身定义为奇怪地重复出现的模板参数:
class FooImpl
:
public FooInterface< FooImpl >
{
private:
// implementation
friend class FooInterface< FooImpl > ;
void do_foo() { std::cout << "Foon"; }
};
class AnotherFooImpl
:
public FooInterface< AnotherFooImpl >
{
private:
// implementation
friend class FooInterface< AnotherFooImpl >;
void do_foo() { std::cout << "AnotherFoon"; }
};
另一种选择是对接口的不同实现进行参数化。这一次,类模板依赖于模板模板参数和非类型参数
template<template<int> class F, int X>
class BarInterface
:
public enable_down_cast< F<X> >
{
private:
// dependent name now in scope
using enable_down_cast< F<X> >::self;
public:
// interface
void bar() { self()->do_bar(); }
protected:
// disable deletion of Derived* through Base*
// enable deletion of Base* through Derived*
~BarInterface() = default; // C++11 only, use ~BarInterface() {} in C++98/03
};
然后,实现是另一个类模板,它从接口派生,其本身和非类型参数都作为参数
template< int X >
class BarImpl
:
public BarInterface< BarImpl, X >
{
private:
// implementation
friend class BarInterface< ::BarImpl, X >;
void do_bar() { std::cout << X << "n"; }
};
这就是你对它们的称呼:
int main()
{
FooImpl f1;
AnotherFooImpl f2;
BarImpl< 1 > b1;
BarImpl< 2 > b2;
f1.foo();
f2.foo();
b1.bar();
b2.bar();
return 0;
}
你问题中的类不太符合这种一般模式。如果你可能想给Derived
一些类似CRTP的行为,那么你可以做
class Derived1
:
public CRTP< Derived1 >
{
};
template<int I>
class Derived2
:
public CRTPInt< Derived2, I >
{
};
更新:基于https://stackoverflow.com/a/11571808/819272,我发现最初的答案只在Visual Studio 2010上编译,但由于一些特定于Microsoft的不可移植功能,所以没有在gcc上编译。例如,enable_down_cast
中的self()
函数在其派生类中是一个依赖于(模板)的名称,因此在没有显式using
指令的情况下是不可见的。此外,我添加了具有适当保护级别的默认析构函数。最后,我将原来的类enable_crtp
重命名为enable_down_cast
,因为这正是它的作用:手动启用静态多态性,就像编译器自动启用动态多态性一样。
相关文章:
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 使用指向成员的指针将成员函数作为参数传递
- 如何将参数传递给正在使用模板的类
- 是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- 修改函数中的指针(将另一个指针作为参数传递)
- 如何将部分流作为参数传递
- 我正在开发服务器,ip作为参数传递不起作用
- 将成员函数指针作为参数传递给模板方法
- 如何在C++中将迭代器作为函数参数传递
- 将附加参数传递给使用 beast::bind_front_handler 调用的函数
- 如何将一个类的函数作为另一个类的另一个函数的参数传递
- 将参数传递为"const"的奇怪效果
- 如何在 c++ 中将函数作为参数传递?
- 在 C++ 中将非指定类型作为参数传递的最佳方法?
- 使用引用与指针将数组作为参数传递
- 如何将成员函数作为回调参数传递给需要"typedef-ed"自由函数指针的函数?
- 将参数打包的参数传递到 std::queue 中,以便稍后使用不同的函数调用
- 为什么我不能将引用作为 std::async 的函数参数传递
- 如何在不使用指针的情况下将派生类的对象作为参数传递给基类中的函数?
- 将__device__ lambda 作为参数传递给 __global__ 函数