派生类的模板特化

edd*_*ddi 14 c++ templates sfinae c++11

我有一个模板类(我无法修改),让我们称之为SomeClass,我想专门研究仅从特定类派生的类.根据这个答案,我能够在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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

A,A,C
Run Code Online (Sandbox Code Playgroud)

sky*_*ack 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;
}
Run Code Online (Sandbox Code Playgroud)

在wandbox上查看它的启动和运行情况。