私はクラスFooとクラスBarを持っています。それらはstd :: array上のラッパーです。 どちらも派生クラスをいくつか持っています。テンプレートパラメータの制限付きでいくつかの外部テンプレートクラスの部分的な特殊化を定義します
template<typename T, std::size_t N>
struct Foo {
std::array<T, N> data;
};
template<typename T, std::size_t N>
struct FooDerived : Foo <T, N> {};
template<typename T, std::size_t N>
struct Bar {
std::array<T, N> data;
};
template<typename T, std::size_t N>
struct BarDerived : Bar <T, N> {};
そして、私はstd名前空間にタプルインターフェイスを実装します:GET/tuple_size/tuple_element。しかし、これらのメソッドはFooのためにしか利用できず、Fooクラスから派生しているはずです。
namespace std {
template<template<typename, std::size_t> class T, typename TArg, std::size_t NArg>
class tuple_size<T<TArg, NArg>>
: public integral_constant<std::size_t, NArg>
{
};
template<std::size_t I, template<typename, std::size_t> class T, typename TArg, std::size_t NArg>
struct tuple_element<I, T<TArg, NArg>>
{
using type = TArg;
};
} // namespace std
これは機能しますが、バーとバー由来のクラスでも機能します。
私はstd :: enable_ifとstd :: is_base_ofを使用すると考えました。クラスのstd :: enable_ifをテンプレートパラメータとして使用できます。 そして、私が書く場合:
template<template<typename, std::size_t> class T, typename TArg, std::size_t NArg,
typename std::enable_if<std::is_base_of<Foo<TArg, NArg>, T<TArg, NArg>>::value, int>::type = 0>
class tuple_size<T<TArg, NArg>>
: public integral_constant<std::size_t, NArg>
{
};
それはコンパイルエラーにつながる:デフォルトテンプレート引数は、部分的な特殊化で使用することはできません。
Fooクラスと無関係にタプルのようなインタフェースを使用することは禁じられていますか?
例:http://rextester.com/JEXJ27486
更新: は、私は解決策を見つけるようです。 static_assertより柔軟性があります。 部分的な特殊化でデフォルトのテンプレート引数を使用できない場合は、完全なテンプレートの特殊化を使用してクラスを追加します。
template<typename T, typename TArg, std::size_t NArg, typename = void>
struct tuple_resolver;
template<typename T, typename TArg, std::size_t NArg>
struct tuple_resolver<T, TArg, NArg,
typename std::enable_if<std::is_base_of<Foo<TArg, NArg>, T>::value>::type>
: public integral_constant<std::size_t, NArg>
{
using type = TArg;
};
template<template<typename, std::size_t> class T,
typename TArg,
std::size_t NArg>
class tuple_size<T<TArg, NArg>>
: public tuple_resolver<T<TArg, NArg>, TArg, NArg>
{
};
例:http://rextester.com/KTDXNJ90374
私は何 '型名STDわかりません。 :enable_if <...> :: type = 0'は、テンプレートパラメータの宣言としても意味されます。通常の 'typename = std :: enable_if <...> :: type'構文を使用するとどうなりますか? –
Daniel Schepler、私は第4の例からこの構文をとった:[cppreference](http://en.cppreference.com/w/cpp/types/enable_if)。しかし、問題は構文ではありません。'typename = std :: enable_if :: type'でもコンパイルできません。というのも、エラーが示すように、デフォルトのテンプレート引数は部分的な特殊化では使用できないからです。 –
Vladislav
ええ、実際には 'typename std :: enable_if :: type = 0'を使っていますが、ちょっとラウンドアバウトであっても意味があります。 –