2

型の特性とテンプレートの特殊化を少し試しています。例えば:

enum TestEnum
{
    VALUE0 = 0,
    VALUE1 = 1,
    VALUE2 = 2
    //... And so on...
};

template<int Value>
class cTestClass;

//specializations
template<>
class cTestClass<VALUE0>
{
    static int GetVal() { return VALUE0; }
};

template<>
class cTestClass<VALUE1>
{
    static int GetVal() { return VALUE1; }
};

template<>
class cTestClass<VALUE2>
{
    static int GetVal() { return VALUE2; }
};

typedef cTestClass<VALUE0> cClassVal0; //(1)
typedef cTestClass<VALUE1> cClassVal1; //(2)
typedef cTestClass<VALUE2> cClassVal2; //(3)

//Later in the code
template<int Value>
cTestClass<Value>* Create()
{
    return new cTestClass<Value>(/*..*/);
}

//And using the upper function
cClassVal2* pTestClass = Create<VALUE2>();

これは絶対にうまくいきます。目標は、インターフェイスのユーザーがテンプレートとテンプレート パラメーターを扱わないようにする方法を提供することです ( Create()を使用する以外に)。これが、コードの下部にある typedef の理由です。

いいえ、次に達成したいことは次のとおりです。cTestClassには、メンバー関数を介してアクセスできるメンバー変数が1つ必要です。特定の状況では、ユーザーがメンバー変数を変更できるようにするか、メンバー変数を変更できないようにする必要があります。したがって、基本的にこれは 2 つのメンバー関数を意味し、1 つは const 参照 (変更不可) または非 const (変更可能) としてメンバーを返します。問題は、これらの両方のメンバー関数が提供されている場合、ユーザーは常にメンバー変数を変更する機会があることです。したがって、コンパイル時に適切なメンバー関数を選択し、ユーザーに正しいメンバー関数を 1 つだけ提供したいと考えています。

私が思いついた唯一の解決策は、基本的に次のようになります。

template<int Value, bool ConstAccess>
class cTestClass;

//specializations
template<>
class cTestClass<VALUE0, true>
{
    const std::string& get() const
    {
        return m_strName;
    }

    static int GetVal() { return VALUE0; }

private:
    std::string m_strName;
};

template<>
class cTestClass<VALUE0, false>
{
    std::string& get()
    {
        return m_strName;
    }

    static int GetVal() { return VALUE0; }

private:
    std::string m_strName;
};

//For every upcoming cTestClass two specializations

typedef cTestClass<VALUE0, true> cConstObjectVal0;
typedef cTestClass<VALUE0, false> cObjectVal0;
//And for the rest...

これは本当に不必要なコードの重複であるという事実に加えて、考えられるすべての VALUE に対して常に 2 つの typedef を指定する必要があります。しかし、ユーザーはその選択に直面するべきではなく、常に上記の型を使用できる必要があります (1、2、3 を参照)。

これは可能ですか?

少しググって、次のサイトにたどり着きました: ACCU:: An Introduction to C++ traits . この説明は設計図と一致しているように見えますが、実際にはそれらをまとめることはできません。私が見つけた別の可能性は、ここで説明されています: C++ Template specialization to provide extra member function? 関数を 1 つ追加するだけでも可能ですが、それでも typedef の問題は解決しません。

4

1 に答える 1

0

SFINAEを使用してみることができます:

typedef char True;
typedef long False;

template <typename VALUE0, typename IsConst>
class cTestClass
{
public:

    template <typename T, T> struct TypeCheck {};

    const std::string& get(TypeCheck<IsConst, True >* dummy = NULL);
          std::string& get(TypeCheck<IsConst, False>* dummy = NULL);
}

typedef cTestClass<VALUE0, True>  cConstObjectVal0;
typedef cTestClass<VALUE0, False> cObjectVal0;

私はまだそれをコンパイルしようとはしませんでしたが、一般的な原則は、関数の 1 つが適切にコンパイルされないようにすることです。その後、SFINAEの原則により、コンパイラは間違ったバージョンを破棄します。

于 2012-11-20T15:33:08.957 に答える