2017-08-14 136 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