web-dev-qa-db-ja.com

(部分的に)依存型の非型テンプレートパラメーターを特殊化する

疲れているかもしれませんが、この単純な部分特殊化で立ち往生しています。これは、_non-type template argument specializes a template parameter with dependent type 'T'_のために機能しません。

_template <typename T, T N> struct X;
template <typename T>      struct X <T, 0>;
_

_0_をT(0)、_T{0}_、または_(T)0_に置き換えても効果はありません。それで、この専門化は可能でさえありますか?

24
iavr

標準の段落[temp.class.spec] 14.5.5/8を参照してください。

特殊化された非型引数に対応するテンプレートパラメータの型は、特殊化のパラメータに依存してはなりません。 [例:

template <class T, T t> struct C {};
template <class T> struct C<T, 1>; // error

template< int X, int (*array_ptr)[X] > class A {};
int array[5];
template< int X > class A<X,&array> { }; // error

—例を終了]

編集に対する答え:最も簡単な回避策は、タイプ以外のテンプレートパラメータをタイプ1に置き換えることです。

#include <type_traits>

template <typename T, typename U>
struct X_;

template <typename T, T N>
struct X_<T, std::integral_constant<T, N>> {};

template <typename T>
struct X_<T, std::integral_constant<T, 0>> {};

template <typename T, T N>
struct X : X_<T, std::integral_constant<T, N>> {};
23
Constructor

Yakkのソリューションを使用したソリューション:

#include <iostream>
#include <type_traits>

template <typename T, T N, typename = void > 
struct X {
  static const bool isZero = false;
};

template <typename T, T N>
struct X < T, N, typename std::enable_if<N == 0>::type > {
  static const bool isZero = true;
};

int main(int argc, char* argv[]) {
    std::cout << X <int, 0>::isZero << std::endl;
    std::cout << X <int, 1>::isZero << std::endl;
    return 0;
}

ライブデモ

7
Sam Cristall

template引数のリストの最後にtypename=voidパラメーターを追加してから、専門分野でstd::enable_if_t<条件>を使用してワイルドになります。

テンプレートに整数値を渡す必要があります。タイプTが整数型でない場合、最初と2番目のテンプレートの両方が機能しません。

型付きテンプレートパラメータとしてTraitsを渡して、値Nを指定できます。

#include <iostream>

// error: ‘double’ is not a valid type for a template non-type parameter
template <typename T, T N> struct X0;

// error: ‘double’ is not a valid type for a template non-type parameter
template <typename T, T N, int = 0> struct X1;



template <typename T, T N>
struct IntegralTraits {
    static constexpr T Value() { return N; }
};

template <typename T, typename Traits = void>
struct X2 {
    static constexpr T Value() { return Traits::Value(); }
};

template <typename T>
struct X2<T, void> {
    static constexpr T Value() { return T(); }
};


int main() {
    // error: ‘double’ is not a valid type for a template non-type parameter
    // X0<double, 0>();

    // error: ‘double’ is not a valid type for a template non-type parameter
    // X1<double, 0>();

    X2<int> a;
    X2<double, IntegralTraits<int, 1>> b;

    std::cout.precision(2);
    std::cout << std::fixed  <<  a.Value() << ", "<< b.Value() << '\n';
    return 0;
}

整数型に限定する場合は、大きな型を選択してください。

template <typename T, std::size_t N = 0> struct X {};
0
user2249683