2

テンプレートに基づいてメンバーを持っている、または持っていないクラスを持つことはできますか?架空のコード:

template <typename HasBazMember=true>
class Foo {
  int bar;

  ConditionallyHaveMember<int, HasBazMember> baz;
};

したがって、上記では、Fooにメンバー「baz」を持たせ、Fooには持たせないようにします。

4

2 に答える 2

4

特殊化なしのC++11のソリューション:

class empty {};

template <typename T>
struct wrap { T wrapped_member; };

template <bool HasBazMember=true>
class Foo : private std::conditional<HasBazMember, wrap<int>, empty>::type {
public:
  int bar;

  int& baz() {
    static_assert(HasBazMember, "try using baz without HasBaz");
    return static_cast<wrap<int>&>(*this).wrapped_member;
  }
};


int main()
{
  Foo<true> t;
  t.baz() = 5;

  Foo<false> f;
  f.baz() = 5; // ERROR
}

EBOのおかげで、の場合はスペースのオーバーヘッドがないことに注意してくださいHasBazMember=false

于 2013-01-08T22:27:51.643 に答える
2

はい、できますが、クラス全体を専門にする必要があります。例:

template< bool HasBazMember = true >
class Foo {
  int bar;
  int baz;
};

template<>
class Foo< false > {
  int bar;
};

ロジックを分離できる場合は、それらのメンバーを基本クラスに配置して、クラス全体のコードを複製する必要がないようにすることができます。例えば、

template< bool HasBazMember >
class FooBase
{
protected:
   int baz;
};

template<>
class FooBase< false >
{
    // empty class
    // the Empty Base Optimization will make this take no space when used as a base class
};

template< bool HasBazMember = true >
class Foo : FooBase< HasBazMember >
{
    int bar;
};

またはBoost.CompressedPairを使用します:

struct empty {};

template< bool HasBazMember = true >
class Foo
{
    boost::compressed_pair<
        int
      , typename std::conditional< HasBazMember, int, empty >::type
    > bar_and_maybe_baz_too;
};
于 2013-01-08T22:22:27.803 に答える