2

この質問はこれに続きます:関数のオーバーロードとテンプレート推論の優先順位

次のクラスを検討します。

template<typename T1, typename T2> 
class Base {};

class Derived0 : public Base<double, double> {};

template<typename T1, typename T2, typename T3> 
class Derived1 : public Base<T1, T2> {};

template<typename T1, typename T2, typename T3, typename T4> 
class Derived2 : public Base<T3, T4> {};

そして、次の機能:

template<typename T> f(const T& x); // version A
template<typename T1, typename T2> f(const Base<T1, T2>& x); // version B

私の問題は、(ok)を呼び出しf(double)、(ok)を呼び出しますが、呼び出すことです(最初にある他の質問へのリンクを参照してください)。version Af(Base<double, double>)version Bf(Derived1<double, double, double>)version A

C ++ 11を使用して、派生したすべてのメンバーをブロックしversion Aて強制する方法は?version BBase<T1, T2>T1T2

注:可能であれば、ヘルパークラスを追加することは避け、提供されたクラスにメンバーを追加することをお勧めします。

4

2 に答える 2

3

これがあなたのために働くかもしれない特性です。

特性クラス:

#include <type_traits>

template <typename, typename> struct Base { };

template <typename T> struct isbase
{
    typedef char yes;
    typedef yes no[2];

    template <typename U, typename V> static yes & test(Base<U, V> const &);
    static no & test(...);

    static bool const value = sizeof(test(std::declval<T>())) == sizeof(yes);
};

応用:

#include <iostream>

template <typename T>
typename std::enable_if<!isbase<T>::value>::type f(T const &)
{
    std::cout << "f(T const &)\n";
}

template <typename T1, typename T2>
void f(Base<T1, T2> const &)
{
    std::cout << "f(Base<T1, T2> const &)\n";
}

例:

template<typename T1, typename T2, typename T3>
struct Derived1 : public Base<T1, T2> {};

int main()
{
    std::cout << isbase<double>::value << std::endl;
    std::cout << isbase<Base<int, char>>::value << std::endl;
    std::cout << isbase<Derived1<bool, bool, bool>>::value << std::endl;

    f(double{});
    f(Base<int, char>{});
    f(Derived1<bool, float, long>{});
}

一般化:タイプがテンプレートインスタンスから派生しているかどうかを確認するために、より一般的な特性を作成できます。

template <typename T, template <typename...> class Tmpl>
struct derives_from_template
{
    typedef char yes;
    typedef yes no[2];

    template <typename ...Args> static yes & test(Tmpl<Args...> const &);
    static no & test(...);

    static bool const value = sizeof(test(std::declval<T>())) == sizeof(yes);
};

使用法:derives_from_template<T, Base>::valueなど。

于 2012-12-16T14:09:19.490 に答える
0

Bクラステンプレートにメンバーとしてマーカータイプを指定し、存在する場合に一般的なtempkateのインスタンス化を失敗させることができると思います。通常、SFINAEは逆の方法で機能しますが、間接参照を使用しても機能するはずです。

template<typename T1, typename T2> 
class Base {
public:
    struct isBase {};
};

template <typename T>
struct is_base {
    template <typename S> char (&test(typename S::isBase*))[1];
    template <typename S> char (&test(...))[2];
    enum { value = sizeof(test<T>(0)) == 1 };
};

template <typename T>
typename std::enable_if<!is_base<T>::value>::type f(T value) {
    ...
};

このソリューションは基本的にKerrekSBのソリューションと同様のことを行いますが、サポートされているタイプを明示的にスペルアウトする必要はありません。タグisBasd(おそらくよりユニークなスペルである必要があります)を使用して、タイプBaseまたは派生オブジェクトを検出します。

于 2012-12-16T14:09:40.900 に答える