标签: crtp

如何为所有派生类型部分专门化类模板?

我想部分专门化一个现有的模板,我无法改变(std::tr1::hash)基类和所有派生类.原因是我使用奇怪的重复模板模式进行多态,并且哈希函数在CRTP基类中实现.如果我只想部分专门用于CRTP基类,那么它很简单,我可以写:


namespace std { namespace tr1 {

template <typename Derived>
struct hash<CRTPBase<Derived> >
{
    size_t operator()(const CRTPBase<Derived> & base) const 
    { 
        return base.hash(); 
    }
};

} }
Run Code Online (Sandbox Code Playgroud)

但是这种专门化只与实际的派生类不匹配CRTPBase<Derived>.我想要的是一种编写部分特化的方法,Derived当且仅当它来源于CRTPBase<Derived>.我的伪代码是


namespace std { namespace tr1 {

template <typename Derived>
struct hash<typename boost::enable_if<std::tr1::is_base_of<CRTPBase<Derived>, Derived>,
    Derived>::type>
{
    size_t operator()(const CRTPBase<Derived> & base) const 
    { 
        return base.hash(); 
    }
};

} }
Run Code Online (Sandbox Code Playgroud)

......但是,这并不工作,因为编译器不能告诉大家,enable_if<condition, Derived>::typeDerived.如果我可以更改std::tr1::hash,我只需添加另一个虚拟模板参数boost::enable_if,如enable_if文档所建议的那样,但这显然不是一个很好的解决方案.有没有解决这个问题的方法?我是否必须在每个unordered_set或 …

c++ partial-specialization derived-class crtp

9
推荐指数
1
解决办法
4381
查看次数

将基于策略的设计与C++中的CRTP相结合

我正在尝试编写一个基于策略的宿主类(即一个继承自其模板类的类),其中一个扭曲,其中策略类也由宿主类进行模板化,以便它可以访问其类型.这可能有用的一个例子是策略(实际上像mixin一样使用),使用多态clone()方法扩充宿主类.这是我正在尝试做的最小例子:

template <template <class> class P>
struct Host : public P<Host<P> > {
  typedef P<Host<P> > Base;
  typedef Host* HostPtr;
  Host(const Base& p) : Base(p) {}
};

template <class H>
struct Policy {
  typedef typename H::HostPtr Hptr;
  Hptr clone() const {
    return Hptr(new H((Hptr)this));
  }
};

Policy<Host<Policy> > p;
Host<Policy> h(p);

int main() {
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

遗憾的是,这不能编译,在我看来像循环类型依赖:

try.cpp: In instantiation of ‘Host<Policy>’:
try.cpp:10:   instantiated from ‘Policy<Host<Policy> >’
try.cpp:16:   instantiated from here
try.cpp:2: error: invalid use of incomplete type ‘struct …
Run Code Online (Sandbox Code Playgroud)

c++ polymorphism policy templates crtp

9
推荐指数
1
解决办法
1964
查看次数

C++:奇怪的重复模板模式是什么?并且可以奇怪地重复模板模式取代虚拟功能?

我没有对问题的准确描述,所以我只是问这是否可能(如果是的话,其他一些信息会很棒).

程序员告诉我,你可以避免虚函数/多态导致的运行时开销.他说为了避免运行时开销,你可以在名为Curiously_recurring_template_pattern的模式中使用模板,它看起来像这样:

class Derived : public Base<Derived>
{
  // ... implementation here
};
Run Code Online (Sandbox Code Playgroud)

这个奇怪的重复模板模式如何工作?

如何使用Curiously-Recurring-Template-Pattern替换正常的虚函数/多态?

我弄错了吗?

c++ templates virtual-functions crtp

9
推荐指数
1
解决办法
4778
查看次数

C++低延迟设计:用于工厂实现的函数调度v/s CRTP

作为系统设计的一部分,我们需要实现工厂模式.结合Factory模式,我们还使用CRTP来提供一组基本功能,然后可以通过Derived类进行自定义.

示例代码如下:

class FactoryInterface{
    public:
     virtual void doX() = 0;
};

//force all derived classes to implement custom_X_impl 
template< typename Derived, typename Base = FactoryInterface>
class CRTP : public Base 
{
    public:
    void doX(){
        // do common processing..... then
        static_cast<Derived*>(this)->custom_X_impl();
    }
};

class Derived: public CRTP<Derived>
{
    public:
        void custom_X_impl(){
        //do custom stuff
        }
};
Run Code Online (Sandbox Code Playgroud)

虽然这种设计很复杂,但它确实提供了一些好处.初始虚函数调用之后的所有调用都可以内联.派生类custom_X_impl调用也是有效的.

我编写了一个比较程序来比较使用函数指针和虚函数的类似实现(紧密循环,重复调用)的行为.这个设计为gcc/4.8与O2和O3取得了胜利.

然而,C++专家昨天告诉我,大型执行程序中的任何虚函数调用都需要一个可变的时间,考虑到缓存未命中,我可以使用C样式函数表查找和gcc函数列表来实现更好的性能.但是我仍然看到上面提到的示例程序的成本的2倍.

我的问题如下:1.大师的断言是真的吗?对于任何一个答案,我可以参考任何链接.2.我是否可以参考任何低延迟实现,有一个基类使用函数指针在派生类中调用自定义函数?3.有关改进设计的建议吗?

任何其他反馈总是受欢迎的.

c++ gcc class-design crtp low-latency

9
推荐指数
1
解决办法
1022
查看次数

使用Clang中的静态constexpr奇怪地重现模板模式(CRTP)

请考虑下面的简单示例:

#include <iostream>

template <typename T>
class Base
{
public:
    static constexpr int y = T::x;
};

class Derived : public Base<Derived>
{
public:
    static constexpr int x = 5;
};


int main()
{
    std::cout << Derived::y << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

在g ++中,这可以很好地编译5并按预期打印.但是,在Clang中,它无法编译错误no member named 'x' in 'Derived'.据我所知,这是正确的代码.我正在做什么有什么问题,如果没有,有没有办法让这个工作在Clang?

c++ templates clang crtp c++11

9
推荐指数
1
解决办法
447
查看次数

关于CRTP静态多态性的困惑

我正试着绕着CRTP.有一些很好的资料来源,包括这个论坛,但我认为我对静态多态性的基础知识有些困惑.查看以下维基百科条目:

template <class T> 
struct Base
{
    void implementation()
    {
        // ...
        static_cast<T*>(this)->implementation();
        // ...
    }

static void static_func()
{
    // ...
    T::static_sub_func();
        // ...
    }
};

struct Derived : public Base<Derived>
{
    void implementation();
    static void static_sub_func();
};
Run Code Online (Sandbox Code Playgroud)

我理解这有助于我在派生类中使用不同的implementation()变体,有点像编译时虚函数.但是,我的困惑是我觉得我不能有像这样的功能

void func(Base x){
    x.implementation();
}
Run Code Online (Sandbox Code Playgroud)

就像我使用普通继承和虚函数一样,由于Base被模板化,但我必须指定

func(Derived x)
Run Code Online (Sandbox Code Playgroud)

或使用

template<class T> 
func(T x)
Run Code Online (Sandbox Code Playgroud)

那么CRTP实际上在这个上下文中给我带来了什么,而不是简单地在Derived :: Base中简单地隐藏/实现该方法?

struct Base
{
    void implementation();

struct Derived : public Base
{
    void implementation();
    static void static_sub_func();
};
Run Code Online (Sandbox Code Playgroud)

c++ crtp

9
推荐指数
2
解决办法
3537
查看次数

及时派生

有一种不太常见的C++习语,我过去常常使用过好几次.我似乎无法记住它是否有一个通常使用的名称来描述它.

它与mixins,CRTP类型擦除有一定关系,但并不是特别相关.

当您想要向类添加一些实现时,会发现问题,但您不希望将它放在类或它派生的任何类中.这样做的一个原因可能是类可能是继承层次结构的一部分,其中实现应该只发生一次.

暂时搁置一些问题,例如层次结构是否应该具有具体的非叶类,或者在某些情况下是否可以选择虚拟继承,我知道在模板类中提供实现的一种解决方案来源于它的模板参数.然后,这允许您在创建实例时使用模板,但之后只能通过指针使用对象或引用其中一个基础(在松散的意义上,类型擦除的位置).

一个例子可能是你有一个侵入性引用计数.你的所有类都来自一个引用计数接口,但你只希望引用计数本身和引用计数方法的实现出现一次,所以你将它们放在派生模板中 - 让我们调用它ImplementsRC<T>.现在你可以像这样创建一个实例:

ConcreteClass* concrete = new ImplementsRC<ConcreteClass>();
Run Code Online (Sandbox Code Playgroud)

我正在掩盖诸如由多个模板化重载等组成的转发构造函数.

所以,希望我已经明确了成语是什么.现在回到我的问题 - 这个成语是否有一个被接受的,或者至少是一般使用的名字?

c++ idioms mixins crtp type-erasure

8
推荐指数
1
解决办法
661
查看次数

如何实现编译时检查转发在CRTP中是否有效?

我有一个普通的旧CRPT(请不要因访问限制而分心 - 问题与他们无关):

 template<class Derived>
 class Base {
     void MethodToOverride()
     {
        // generic stuff here
     }
     void ProblematicMethod()
     {
         static_cast<Derived*>(this)->MethodToOverride();
     } 
 };
Run Code Online (Sandbox Code Playgroud)

像往常一样打算像这样使用:

 class ConcreteDerived : public Base<ConcreteDerived> {
     void MethodToOverride()
     {
        //custom stuff here, then maybe
        Base::MethodToOverride();
     }
 };
Run Code Online (Sandbox Code Playgroud)

现在static_cast困扰我了.我需要一个向下投射(不是向上投射),所以我必须使用一个明确的演员.在所有合理的情况下,强制转换都是有效的,因为当前对象确实是派生类.

但是如果我以某种方式改变层次结构并且演员现在变得无效呢?

我可以以某种方式强制执行编译时检查,在这种情况下显式向下转换有效吗?

c++ casting crtp static-cast upcasting

8
推荐指数
1
解决办法
1320
查看次数

CRTP - 从基类检查派生的符合要求的类

奇怪的重复模板模式可用于实现一种静态多态性.例如:

#include <iostream>

template<
 class Derived
>
struct Base
{
    static void print ( )
    {
        std::cout << Derived::number_to_print << '\n';
    }
};

struct Derived final :
    Base<
     Derived
    >
{
    static constexpr unsigned int number_to_print = 27;
};

int main ( )
{
    Derived::print();
}
Run Code Online (Sandbox Code Playgroud)

这表现得如预期和打印27.

现在,我想向基类添加检查以断言派生类满足某些要求.在上面给出的示例中,此类检查可以是:

#include <iostream>
#include <type_traits>

template<
 class Derived
>
struct Base
{
    // --- Checks begin
    static_assert( std::is_same<
         decltype(Derived::number_to_print),
         unsigned int
        >::value,
        "static member `number_to_print' should be of type `unsigned int'" …
Run Code Online (Sandbox Code Playgroud)

c++ crtp c++14

8
推荐指数
1
解决办法
312
查看次数

CRTP 相对于抽象类的优势?

我对“奇怪的重复模板模式”的概念很陌生,我正在此处阅读有关其潜在用例的信息。

在那篇文章中,作者描述了一个简单的情况,其中我们有两个或多个具有一些通用功能的类:

class A {
public:
  int function getValue() {...}
  void function setValue(int value) {...}

  // Some maths functions
  void scale() {...}
  void square() {...}
  void invert() {...}
}

class B {
public:
  double function getValue() {...}
  void function setValue(double value) {...}

  // Some maths functions
  void scale() {...}
  void square() {...}
  void invert() {...}
}
Run Code Online (Sandbox Code Playgroud)

作者认为,我们可以使用 CRTP,而不是在每个类中重复通用功能:

template <typename T>
struct NumericalFunctions
{
    void scale(double multiplicator);
    void square();
    void invert();
};

class A : public NumericalFunctions<A>
{ …
Run Code Online (Sandbox Code Playgroud)

c++ abstract-class crtp

8
推荐指数
1
解决办法
2555
查看次数