0

テンプレート化されたクラスがあり、型が double の場合にのみ特定のコンストラクターを有効にしたいと考えています。このコードの何が問題になっていますか?

template<typename T>
class B: public A<T>
{
public:
    B(int arg1=0, typename boost::enable_if_c<boost::is_same<T, double>::value>=0);
}

int main(int argc,char *argv[])
{
B<double> B( 6, 6 );
}

エラーが表示されます:「タイプ 'boost::enable_if_c' のパラメーターのデフォルト引数のタイプは 'int' です」が、これが何を意味するのかわかりません。

よろしくお願いします。

4

3 に答える 3

7

まあ、あなたは本当にそれを行うことはできません。Tではないものをdouble指定すると、コンパイラは を解決しようとしますenable_if_c<false>::typeが、これは失敗し、コンストラクターだけでなく、クラスのインスタンス化全体が失敗します。

C++11 のデフォルトの関数テンプレート引数を使用して、同じことを実現できます。

以下のコードは、コードで使用した機能の C++11 バージョンを使用して実装しboostます。

#include <type_traits>

template<typename T>
class B {
public:
    // T == double -> this ctor can be used
    template<typename U = T, class = typename std::enable_if<std::is_same<U, double>::value>::type>
    B(int arg1, double arg2) {}

    // Default ctor, available to every class.
    B() {}
};

int main(int argc,char *argv[])
{
    B<double> b_double( 6, 6 );
    B<int> b_int;

    // This line fails
    //B<int> b_fails(6, 6);
}
于 2012-08-24T21:28:40.250 に答える
2

この場合、SFIANE は使用できません。これは、クラステンプレート引数の置換が失敗した場合ではなく、関数テンプレート引数の置換が失敗した場合にのみ機能するためです。

必要なのは専門化です。

しかし、私が理解しているように、あなたのdoubleケースでは一般的なケースの実装をコピーする必要がありますが、新しいコンストラクターのみを追加してください。

この場合、私は少し配線されたテクニックをお勧めします。専門分野の一般的なケースから派生させることができます。

次に、2 つの問題に直面します。

  1. double派生する特殊な一般的なケースがまだ必要です
  2. 一般的なケースのデフォルト コンストラクターを呼び出すのではなく、特殊なコンストラクターを呼び出す必要があります。

では、次のようにします。

template<typename T, bool = false>
class B
{
public:
    B() { std::cout << "B common\n"; }
    void yahoo() { std::cout << "yahoo!\n"; }

protected:
    struct internal_t;
    B(internal_t*){}

};

template <>
struct B<double, false>: public B<double, true>
{
    B(int, int):B<double, true>(0) { std::cout << "B double\n"; }
};

int main(int argc,char *argv[])
{
    B<int> ib;
    B<double> b(2,5);

    ib.yahoo();
    b.yahoo();
}
于 2012-08-24T20:45:46.387 に答える
0
B(int arg1=0, typename boost::enable_if_c<boost::is_same<T, double>::value>=0);

boost::enable_if_c型を指定する2 番目の引数、 ::type、およびパラメーター名を忘れました。

のラインに沿って何かが必要な場合はB(int arg1=0, int arg2=0)、使用します

B(int arg1=0,
  typename boost::enable_if_c<boost::is_same<T, double>::value, int>::type arg2=0);

さらに良いことに、下線付きの c バージョンの enable if は使用しないでください。次の場合は enable を使用してください。

B(int arg1=0,
  typename boost::enable_if<boost::is_same<T, double>, int>::type arg2=0);
于 2012-08-24T20:25:20.113 に答える