16

CRTPを使用して、次のようなコードを書くことがあります。

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

// this was copy-pasted from Foo some days later
struct Bar : Base<Foo, ...>
{
   ...
};

そして、デバッガーでコードをトレースし、Barのメンバーがで使用されていないことを確認するまで、何が問題になっているのかを理解するのは非常に困難Baseです。

コンパイル時にこのエラーを明らかにするにはどうすればよいですか?

(私はMSVC2010を使用しているので、いくつかのC ++ 0x機能とMSVC言語拡張機能を使用できます)

4

5 に答える 5

17

C++0x では、簡単な解決策があります。ただし、MSVC10に実装されているかどうかはわかりません。

template <typename T>
struct base
{
private:
    ~base() {}
    friend T;
};

// Doesn't compile (base class destructor is private)
struct foo : base<bar> { ... };
于 2011-08-30T07:35:50.490 に答える
11

次のようなものを使用できます。

template<class T> class Base {
protected:
   // derived classes must call this constructor
   Base(T *self) { }
};

class Foo : public Base<Foo> {
public:
   // OK: Foo derives from Base<Foo>
   Foo() : Base<Foo>(this) { }
};

class Moo : public Base<Foo> {
public:
   // error: constructor doesn't accept Moo*
   Moo() : Base<Foo>(this) { }
};

class Bar : public Base<Foo> {
public:
   // error: type 'Base<Bar>' is not a direct base of 'Bar'
   Bar() : Base<Bar>(this) { }
};
于 2010-12-11T17:42:25.787 に答える
2
template<typename T, int arg1, int arg2>
struct Base
{
    typedef T derived_t;
};

struct Foo : Base<Foo, 1, 2>
{
    void check_base() { Base::derived_t(*this); } // OK
};

struct Bar : Base<Foo, 1, 2>
{
    void check_base() { Base::derived_t(*this); } // error
};

このコードはAmnon's answerに基づいていますが、チェック コードには派生クラスの名前が含まれていないため、変更せずにコピーして貼り付けることができます。

于 2010-12-12T19:40:01.737 に答える
0

I can use a macro

#define SOMENAMESPACE_BASE(type, arg1, arg2) type : Base<type, arg1, arg2>

but I don't want to use macros if better solution exists.

于 2010-12-11T17:04:13.897 に答える
0

派生型を知る方法はありません。Fooから派生したことを強制することはできBase<Foo>ますが、他のクラスもそれから派生しないことを強制することはできません。

于 2010-12-11T16:57:49.360 に答える