15

タイプがデータメンバーであるテンプレートクラスがありstd::vector<T>ます。ここで、Tはテンプレートクラスのパラメーターでもあります。

私のテンプレートクラスには、これを行うロジックがかなりあります。

T &value = m_vector[index];

std :: vectorの[]演算子はbool-referenceを返さず、異なる型を返すため、Tがブール値の場合はコンパイルされないようです。

いくつかの選択肢(私はそれらのどれも好きではありませんが):

  • テンプレートパラメータとしてboolを使用してはならないことをユーザーに伝えます
  • 私のクラスをboolに特化しています(ただし、これにはコードの重複が必要です)

std :: vectorにboolに特化しないように指示する方法はありませんか?

4

6 に答える 6

10

これはコンテナではないため、テンプレート化されたコードを、データがで表される場合Tと同じように定期的に動作させることはできません。@Mark Ransomが指摘しているように、代わりに、たとえば次のような特性を使用して使用できます。boolstd::vector<bool>std::vector<char>

template<typename T> struct vector_trait { typedef std::vector<T> type; };
template<> struct vector_trait<bool> { typedef std::vector<char> type; };

次に、typename vector_trait<T>::type現在使用している場所で使用しますstd::vector<T>。ここでの欠点は、からに変換するためにキャストを使用する必要があることcharですbool

あなた自身の答えで提案されている代替案は、暗黙の変換とコンストラクターでラッパーを書くことです

template<typename T>
class wrapper
{
public:
        wrapper() : value_(T()) {}
        /* explicit */ wrapper(T const& t): value_(t) {}
        /* explicit */ operator T() { return value_; }
private:
        T value_;
};

std::vector< wrapper<bool> >キャストせずにどこでも使用できます。ただし、実際のパラメーターを含む標準の変換シーケンスboolは、ユーザー定義の変換とは異なる動作をするため、これには欠点もありますwrapper<bool>(コンパイラーは、最大で1つのユーザー定義の変換と、必要な数の標準変換を使用できます)。これは、関数のオーバーロードを伴うテンプレートコードが微妙に壊れることを意味します。上記のコードのキーワードのコメントを解除することもできますがexplicit、これにより冗長性が再び導入されます。

于 2013-01-17T20:54:20.987 に答える
4

std::vector<char>代わりに使用してください。

于 2013-01-17T20:58:59.687 に答える
4

次のことはあなたのために働きますか?

template <typename T>
struct anything_but_bool {
    typedef T type;
};

template <>
struct anything_but_bool<bool> {
    typedef char type;
};

template <typename T>
class your_class {
    std::vector<typename anything_but_bool<T>::type> member;
};

それほど派手ではありませんが、名前anything_but_boolはおそらくprevent_bool同じか類似しているはずです。

于 2013-01-17T21:05:36.190 に答える
1

カスタムプロキシクラスを使用して、boolを保持できます。

class Bool
{
  public:
    Bool() = default;
    Bool(bool in) : value(in) {}

    Bool& operator=(bool in) {value = in;}
    operator bool() const& {return value;}

  private:
    bool value;
};

これはあなたの目的のために少し微調整を必要とするかもしれません、しかしそれは通常私がこれらの場合にすることです。

于 2013-01-17T21:07:01.923 に答える
1

私はあなたのすべての入力に基づいて、さらにエレガントな解決策を見つけました。

まず、1つのメンバーを保持する単純なクラスを定義します。これを呼びましょうwrapperClass

template <typename T>
class wrapperClass
   {
   public:
      wrapperClass() {}
      wrapperClass(const T&value) : m_value(value) {}
      T m_value;
   };

これで、次のようにテンプレートクラスでstd::vectorを定義できます。

std::vector<wrapperClass<T>> m_internalVector;

sizeof(WrapperClass<bool>)も1なので、常に。sizeof(WrapperClass<T>)に等しくなると思いsizeof(T)ます。データ型がブール値ではなくなったため、特殊化は実行されません。

ベクトルから要素を取得する場所では、単に置換します

m_internalVector[index]

m_internalVector[index].m_value

しかし、これは、特性を使用してboolをcharに置き換え、次にキャストを使用してcharとboolを変換する(そしておそらくキャストを再解釈してchar&をbool&に変換する)よりもはるかにエレガントに見えます。

どう思いますか?

于 2013-01-18T10:48:11.647 に答える
0

特殊化を防ぐ方法がありvector<bool>ます。カスタムアロケータを渡す。

std::vector<bool, myallocator> realbool; 

次の記事にいくつかの詳細があります: https ://www.informit.com/guides/content.aspx?g = cplusplus&seqNum = 98

もちろん、これにはvector定義を制御する必要があるため、実際には解決策ではない可能性があります。それとは別に、それ自体のいくつかの欠点もあります...

于 2013-01-17T21:02:54.320 に答える