标签: crtp

使用CRTP时如何避免错误?

使用CRTP有时我会编写如下代码:

// this was written first
struct Foo : Base<Foo, ...>
{
   ...
};

// this was copy-pasted from Foo some days later
struct Bar : Base<Foo, ...>
{
   ...
};
Run Code Online (Sandbox Code Playgroud)

并且很难理解出现了什么问题,直到我在调试器中跟踪代码并看到Bar的成员未被使用Base.

如何在编译时显示此错误?

(我使用MSVC2010,所以我可以使用一些C++ 0x功能和MSVC语言扩展)

c++ crtp

15
推荐指数
2
解决办法
1425
查看次数

对类型相关的模板名称使用声明

当在模板中使用CRTP时(或者通常当模板参数作为基类模板参数传递时),是否无法在using声明中命名基础的成员模板?

template< typename d >
struct base {
    template< typename >
    struct ct {};

    template< typename >
    void ft() {}
};

template< typename x >
struct derived : base< derived< x > > {
     using derived::base::template ct; // doesn't work
     using derived::base::ft; // works but can't be used in a template-id
};
Run Code Online (Sandbox Code Playgroud)

在我看来,这是语言中的一个漏洞,因为使用声明语法生成不包含qualified-id.

using-declaration:
    using typename(opt) nested-name-specifier unqualified-id ; // have this
    using :: unqualified-id ;

unqualified-id:
    identifier
    operator-function-id
    conversion-function-id
    literal-operator-id
    ~ class-name
    ~ …
Run Code Online (Sandbox Code Playgroud)

c++ grammar templates crtp

14
推荐指数
1
解决办法
1814
查看次数

使用派生类的静态constexpr数据成员初始化基类的静态constexpr数据成员

请考虑以下代码:

template<typename T>
struct S { static constexpr int bar = T::foo; };

struct U: S<U> { static constexpr int foo = 42; };

int main() { }
Run Code Online (Sandbox Code Playgroud)

GCC v6.1编译它,clang 3.8拒绝它并带有错误:

2:错误:'U'
结构中没有名为'foo'的成员S {static constexpr int bar = T :: foo; };

哪个编译器是对的?
可能是因为我们尝试在其中使用它时U 不是一个完整的类型S吗?
在这种情况下,它应该被认为是GCC的一个错误,但我想知道我是否正好在bug跟踪器上搜索/打开一个问题...

编辑

与此同时,我向GCC 打开了一个错误.
等待它接受答案.

c++ templates crtp constexpr c++14

14
推荐指数
1
解决办法
1580
查看次数

在 CRTP 基类构造函数中向下转换为派生类:UB 与否?

考虑以下类:

template <class Derived>
class BaseCRTP {
  private:
    friend class LinkedList<Derived>;
    Derived *next = nullptr;

  public:
    static LinkedList<Derived> instances;

    BaseCRTP() {
        instances.insert(static_cast<Derived *>(this));
    }
    virtual ~BaseCRTP() {
        instances.remove(static_cast<Derived *>(this));
    }
};
Run Code Online (Sandbox Code Playgroud)
struct Derived : BaseCRTP<Derived> {
    int i;
    Derived(int i) : i(i) {}
};
Run Code Online (Sandbox Code Playgroud)
int main() {
    Derived d[] = {1, 2, 3, 4};
    for (const Derived &el : Derived::instances) 
        std::cout << el.i << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

我知道,这是不确定的行为来访问的成员DerivedBaseCRTP<Derived>构造函数(或析构函数),因为Derived构造函数执行BaseCRTP<Derived>构造(和析构函数的其他方式)。

我的问题是:在不访问任何成员的 …

c++ crtp downcast undefined-behavior language-lawyer

14
推荐指数
1
解决办法
297
查看次数

C++中的两种不同的mixin模式.(mixin?CRTP?)

我正在研究mixins(用C++编写).我阅读了一些关于mixins的文章,并在C++中发现了两种不同的"近似"mixins模式.

模式1:

template<class Base>
struct Mixin1 : public Base {
};

template<class Base>
struct Mixin2 : public Base {
};

struct MyType {
};

typedef Mixin2<Mixin1<MyType>> MyTypeWithMixins;
Run Code Online (Sandbox Code Playgroud)

模式2 :(可称为CRTP)

template<class T>
struct Mixin1 {
};

template<class T>
struct Mixin2 {
};

struct MyType {
};

struct MyTypeWithMixins : 
    public MyType, 
    public Mixin1<MyTypeWithMixins>, 
    public Mixin2<MyTypeWithMixins> {
};
Run Code Online (Sandbox Code Playgroud)

它们实际上相当吗?我想知道模式之间的实际差异.

c++ design-patterns mixins crtp

13
推荐指数
2
解决办法
1715
查看次数

C++ CRTP虚函数实例化点

我试图了解标准的简单CRTP模式是否有效.

下面的代码编译并按预期工作(在clang上).

但是我对相关标准章节/段落的理解是,虚函数CRTP <Derived,Base> :: DoSomething()的实例化应该在代码的点(B)处,其中Derived的完整声明不是可用.因此内部typedef类型也不应该可用.

任何人都可以指出验证此代码的相关标准章节吗?

换句话说,在这种情况下,虚拟函数被实例化ATFER点C?非常感谢您的任何见解.

弗朗切斯科

//-------------------------
// START CODE

#include <iostream>

struct Type1 {};
struct Type2 {};

struct Base
{
  virtual ~Base() {}
  virtual void DoSomething() = 0;
};

template< typename T, typename U >
struct CRTP : U
{
  virtual void DoSomething() { DoSomething( typename T::Type() ); }

 void DoSomething( Type1 ) { std::cout << "1\n"; }
 void DoSomething( Type2 ) { std::cout << "2\n"; }
};

// (A) point of inst. of CRTP< Derived, …
Run Code Online (Sandbox Code Playgroud)

c++ templates crtp

12
推荐指数
1
解决办法
1079
查看次数

为什么这个C++代码只能在Microsoft编译器上调用模糊方法?

我正在尝试在microsoft C++编译器14.1(Visual Studio 2017)上编译库,但由于对类方法的模糊调用,我得到一个奇怪的错误.经过一些测试后,我分离了以下代码片段:

#include <iostream>

struct Event
{};

template<typename Derived>
struct State
{
public:
    template<typename Fsm>
    void onEvent(Fsm& fsm, const Event& event)
    {
        std::cout << "State::onEvent\n";
    }

};

struct DerivedState
    : State<DerivedState>
{
public:
    using State::onEvent;

    template<typename Fsm>
    void onEvent(Fsm& fsm, const Event& event)
    {
        std::cout << "DerivedState::onEvent\n";
    }

};

struct Context
{};


int main()
{
    DerivedState ds;
    Context context;
    ds.onEvent(context, Event());
}
Run Code Online (Sandbox Code Playgroud)

我得到以下输出:

1> c:\ users\pmas\documents\visual studio

2017\projects\consoleapplication3\consoleapplication3\consoleapplication3.cpp(87): error C2668: 'DerivedState::onEvent': ambiguous call to overloaded function
1>c:\users\pmas\documents\visual studio …
Run Code Online (Sandbox Code Playgroud)

c++ overloading crtp ambiguous-call overload-resolution

12
推荐指数
1
解决办法
437
查看次数

std :: declval vs crtp,无法从不完整类型推断出方法返回类型

我正在尝试做这样的事情(在c ++ 11中):

#include <utility>

template <typename T>
struct base {
    using type = decltype( std::declval<T>().foo() );
};

struct bar : base<bar> {
    int foo() { return 42;}
};

int main() {
    bar::type x;
}
Run Code Online (Sandbox Code Playgroud)

失败与

prog.cc: In instantiation of 'struct base<bar>':
prog.cc:8:14:   required from here
prog.cc:5:46: error: invalid use of incomplete type 'struct bar'
     using type = decltype( std::declval<T>().foo() );
                            ~~~~~~~~~~~~~~~~~~^~~
prog.cc:8:8: note: forward declaration of 'struct bar'
 struct bar : base<bar> {
        ^~~
Run Code Online (Sandbox Code Playgroud)

如何声明bar::fooin 的返回类型的别名base …

c++ crtp decltype c++11 declval

12
推荐指数
1
解决办法
229
查看次数

重用复制和交换习语

我正在尝试将复制和交换习惯用法放入可重用的混音中:

template<typename Derived>
struct copy_and_swap
{
    Derived& operator=(Derived copy)
    {
        Derived* derived = static_cast<Derived*>(this);
        derived->swap(copy);
        return *derived;
    }
};
Run Code Online (Sandbox Code Playgroud)

我打算通过CRTP混合:

struct Foo : copy_and_swap<Foo>
{
    Foo()
    {
        std::cout << "default\n";
    }

    Foo(const Foo& other)
    {
        std::cout << "copy\n";
    }

    void swap(Foo& other)
    {
        std::cout << "swap\n";
    }
};
Run Code Online (Sandbox Code Playgroud)

但是,一个简单的测试显示它不起作用:

Foo x;
Foo y;
x = y;
Run Code Online (Sandbox Code Playgroud)

这仅打印两次"默认",不打印"复制"或"交换".我在这里错过了什么?

c++ mixins crtp assignment-operator copy-and-swap

11
推荐指数
2
解决办法
779
查看次数

如何在MISRA C++之后实现CRTP

我的团队正在开发一个嵌入式系统,我们需要遵循MISRA C++.

我们正在重构代码以使用更少的虚方法,因此我们尝试实现CRTP以使用静态多态而不是动态多态.

但是我们遇到静态多态性需要指针转换的问题,因此我们的静态分析检查器会抱怨.

这是界面

template <typename T>
class UpdateMethod
{
protected:
    ~UpdateMethod() {}
 public:
    void operator()() const
    {
        // [MISRA Rule 5-2-7] violation:
        static_cast<const T*>(this)->update();
    }
};
Run Code Online (Sandbox Code Playgroud)

以下是其中一个实现:

class A
    : public UpdateMethod<A>
{
 public:
    void update() const {}
};
Run Code Online (Sandbox Code Playgroud)

在通过MISRA检查程序时,它会抱怨static_cast(从ptr转换为ptr(e926).

所以,我的问题是:有没有什么好的方法来实现CRTP而不必压制MISRA警告,所以以安全的方式?

仅有关于指针转换的相关问题: MISRA C++ 2008规则5-2-7违规:指针类型的对象不应直接或间接转换为无关指针类型 我在CRTP中具有相同的错误.

编辑:正如前面提到的只有C++ 03而没有像boost这样的外部库.

c++ misra crtp static-cast c++03

11
推荐指数
1
解决办法
374
查看次数