2017-08-14 137 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並不直接從它繼承。相反,您可以非常依賴mixin,並將一些類別與檢測器相結合,您可以將其專用於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