C++ 派生类的模板专门化

C++ 派生类的模板专门化,c++,c++11,templates,sfinae,C++,C++11,Templates,Sfinae,我有一个模板类(我不能修改),让我们称它为SomeClass,我想专门用于只从特定类派生的类。接下来,我能够在gcc 6.3.1中实现这一点,但不幸的是,我需要在gcc 4.9.2中实现这一点,并且在编译时它失败了,说“部分专门化SomeClass不会专门化任何模板参数” 是否有任何方法可以更改以下内容,使其与gcc 4.9.2兼容 #include <iostream> #include <string> using namespace std; struct A

我有一个模板类(我不能修改),让我们称它为
SomeClass
,我想专门用于只从特定类派生的类。接下来,我能够在gcc 6.3.1中实现这一点,但不幸的是,我需要在gcc 4.9.2中实现这一点,并且在编译时它失败了,说“部分专门化
SomeClass
不会专门化任何模板参数”

是否有任何方法可以更改以下内容,使其与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
,而不是直接从中继承。相反,您可以严重依赖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;
}
#包括
#包括
#包括
使用名称空间std;
类驱动工厂{
结构A{
字符串名(){返回“A”;}
};
模板
结构检测器:T{using type=A;};
公众:
模板

使用类型=Detector@AndyG我会得到“A,B,C”如果我没有专门化。我想要A和B的专门化。这看起来像是这个的复制品:如果它不是复制品,那么它是一个近亲,你的答案可能在那里……gcc 4.9.2和all@Drt正如我在OP中提到的——这个问题是我的出发点——我只是不知道如何适应我的需要不要使用4.9.2。@eddi顺便说一句,如果您的示例不是真的精心设计的,那么就有
std::conditional
——在这种情况下,您不需要专门化。@LogicStuff不幸的是,我确实需要专门化,因为
SomeClass
在另一个类中使用(我再次无法更改)为了弄清楚在一些复杂的工厂建设逻辑中使用哪种类型。谢谢,这很有趣。我有权修改A类,但我很确定我会因此被谋杀:)这是一种教育方法。@eddi,正如我所说,它是有效的。这是唯一的优势。美观不是另一个优势。:-d
#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;
}