2017-08-14 18 views
13

私はテンプレートクラス(変更できません)をSomeClassと呼びましょう。特定のクラスから派生したクラスに特化したいと思っています。 this answer私はgcc 6.3.1でこれを実行できましたが、残念ながらgcc 4.9.2でそれを実行する必要があり、コンパイル時にというエラーが発生しました。 "部分的な特殊化SomeClass<T>はテンプレート引数を特化していません"派生クラスのテンプレートの特殊化

gcc 4.9.2で動作させるために以下を変更する方法はありますか?

#include <iostream> 
#include <string> 

using namespace std; 

struct A { 
    string name() { return "A"; } 
}; 

struct B : A { 
    string name() { return "B"; } 
}; 

struct C { 
    string name() { return "C"; } 
}; 

template<typename T, typename = std::enable_if_t<std::is_base_of<A, T>::value>> 
using enable_if_a = T; 

template<typename T> 
struct SomeClass { 
    using Type = T; 
}; 

template<typename T> 
struct SomeClass<enable_if_a<T>> 
{ 
    using Type = A; 
}; 

int main(int, char**) 
{ 
    SomeClass<A>::Type el1; 
    SomeClass<B>::Type el2; 
    SomeClass<C>::Type el3; 

    cout << el1.name() << "," << el2.name() << "," << el3.name() << endl; 
} 

は出力:

A,A,C 
+0

@AndyG私が専門でない場合、私は "A、B、C"を得るだろう。私はAとBの専門化が欲しい。 – eddi

+1

これはこれと重複しているようだ:https://stackoverflow.com/questions/12858839/using-sfinae-for-template-class-specialisation重複していなければあなたの答えはおそらくそこにあります... gcc 4.9.2とすべて –

+0

@Drt私はOPで言及しています - その質問は私の出発点でした - 私は自分のニーズに合わせてそれをどうやって調整するのか分かりません。私の現在の試みは4.9.2で動作しません。 – eddi

答えて

3

少し不自然が、ここでは、少なくとも働く機械です。
基本的な考え方はAを非表示にしており、直接継承しません。代わりに、ミックスインに大きく依存して、SomeClassを特化できる検出器でいくつかのクラスを組み合わせることができます。
短所は、Bのようなクラスはもっと不安定になり、私はそれが終わりにそれを価値があるとは確信していません。直接専門化はおそらくより良いでしょう。

#include <iostream> 
#include <string> 
#include <utility> 

using namespace std; 

class ADerivedFactory { 
    struct A { 
     string name() { return "A"; } 
    }; 

    template<typename T> 
    struct Detector: T { using type = A; }; 

public: 
    template<template<typename> class C> 
    using type = Detector<C<A>>; 
}; 

template<typename T> 
struct AT : T {}; 

template<typename T> 
struct BT : T { 
    string name() { return "B"; } 
}; 

using A = ADerivedFactory::type<AT>; 
using B = ADerivedFactory::type<BT>; 

struct C { 
    string name() { return "C"; } 
}; 

template<typename T> 
struct SomeClass { 
    using Type = T; 
}; 

template<template<typename> class C> 
struct SomeClass<ADerivedFactory::type<C>> 
{ 
    using Type = typename ADerivedFactory::type<C>::type; 
}; 

int main(int, char**) 
{ 
    SomeClass<A>::Type el1; 
    SomeClass<B>::Type el2; 
    SomeClass<C>::Type el3; 

    cout << el1.name() << "," << el2.name() << "," << el3.name() << endl; 
} 

はそれを参照してくださいwandbox上で実行されている:言われていること

は、ここでの実施例です。

+0

ありがとう、これは興味深いです。私はクラスAを変更するアクセス権がありますが、私はこれを行うために殺害されると確信しています:)それは教育的アプローチです。 – eddi

+1

@eddi私が言ったように、うまくいきます。それが唯一の利点です。美しさは別のものではありません。 :-D – skypjack

関連する問題