gpt4 book ai didi

c++ - 如何将模板参数传递给 CRTP?

转载 作者:太空狗 更新时间:2023-10-29 21:04:17 25 4
gpt4 key购买 nike

在下面的代码中:

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 以便我可以传入模板化参数,然后在 Derived 定义中继续?

谢谢,

吉姆

最佳答案

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
};

然后你为你想要的行为类型定义一个接口(interface)类模板

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
};

要获得此接口(interface)的不同实现,只需定义不同的类,每个类都派生自 FooInterface 并将它们自己作为奇怪的重复模板参数:

class FooImpl
:
public FooInterface< FooImpl >
{
private:
// implementation
friend class FooInterface< FooImpl > ;
void do_foo() { std::cout << "Foo\n"; }
};

class AnotherFooImpl
:
public FooInterface< AnotherFooImpl >
{
private:
// implementation
friend class FooInterface< AnotherFooImpl >;
void do_foo() { std::cout << "AnotherFoo\n"; }
};

另一种方法是参数化接口(interface)的不同实现。这一次,类模板同时依赖于一个模板模板参数和一个非类型参数

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
};

实现是另一个类模板,它派生自以自身和非类型参数作为参数的接口(interface)

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 上编译,而不是在 gcc 上编译,因为某些 Microsoft 特定的、不可移植的特性。例如。 enable_down_cast 中的 self() 函数是其派生类中的(模板)依赖名称,因此在没有显式 using 指令的情况下不可见。此外,我还添加了具有适当保护级别的默认析构函数。最后,我将我原来的类 enable_crtp 重命名为 enable_down_cast 因为这正是它所做的:手动启用静态多态性,编译器会自动启用动态多态性。

关于c++ - 如何将模板参数传递给 CRTP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11546478/

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