【问题标题】:template specialization for derived classes派生类的模板特化
【发布时间】:2018-01-22 13:57:09
【问题描述】:

我有一个模板类(我无法修改),我们称它为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

【问题讨论】:

  • @AndyG 如果我不专攻,我会得到“A,B,C”。我想要 A 和 B 的专业化。
  • 这看起来像一个副本:stackoverflow.com/questions/12858839/… 如果它不是一个副本,那么它是一个近亲,你的答案可能就在那里...gcc 4.9.2 和所有
  • @Drt 正如我在 OP 中提到的那样——这个问题是我的出发点——我只是不确定如何根据我的需要调整它。我目前的尝试不适用于 4.9.2。
  • @eddi 顺便说一句,如果您的示例不是真正做作的,则有 std::conditional - 您不需要专门研究这种情况。
  • @LogicStuff 不幸的是我需要专门化,因为SomeClass 用于不同的类(我再次无法更改)以确定在某些复杂的工厂构造逻辑中使用什么类型。跨度>

标签: c++ c++11 templates sfinae


【解决方案1】:

有点做作,但这是一台至少可以工作的机器。
基本思想是隐藏 A 并且不直接从它继承。相反,您可以严重依赖 mixins,并在一个检测器中组合几个类,您可以使用这些类进行专业化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 上查看并运行它。

【讨论】:

  • 谢谢,这很有趣。我有权修改 A 类,但我很确定我会因为这样做而被谋杀 :) 不过这是一种教育方法。
  • @eddi 好吧,正如我所说,它有效。这是唯一的优势。美丽不是另一个。 :-D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-28
  • 1970-01-01
  • 2016-09-26
  • 2017-02-10
  • 1970-01-01
  • 2014-02-04
  • 1970-01-01
相关资源
最近更新 更多