【问题标题】:Template template parameters used as default value for other arguments模板模板参数用作其他参数的默认值
【发布时间】:2019-05-14 10:38:17
【问题描述】:

我正在尝试使用模板模板参数作为其他模板参数的默认值,但是当我尝试使用标识符(模板模板参数名称/id)时,找不到它。 我正在使用 VS 2013。 这个想法是我有一个基于特定类型的模板实例化的“工厂”类我需要返回另一个具有相同数量的参数 (4) 但具有相同专业化的对象。

template<class T1, class T2,class T3, class T4>
class CommandBus
{...}

template <
template<class T1, class T2, class T3, class T4> class ListenerType,
//The Line bellow fails to compile, T1 is not visible
//E0020 identifier "T1" is undefine 
class CommandBusType = CommandBus<T1, T2, T3, T4> >
class CommandBusFactory {
static auto Get() {
        return CommandBusType{};
    }
};

int main{
//Say I would Have some Object :
Listener<int, int ,int int> Listener;
//Withought the Factory I would have to manually generate a ComamndBus of the same specialization (int , int , int, int):
CommandBus<int,int,int,int> cmdBus;


//But I could use a factory, things should look like:
Listener<int, int ,int int> listener;
auto cmdBus = CommandBusFactory<Listener<int,int,int,int>>::Get();
}

我原以为这会起作用,但编译器抱怨说,例如 未找到模板参数 CommandBusType 的默认值 (CommandBus) 的标识符 T1、T2 等

是否可以使用模板模板参数作为其他模板参数的默认值?

【问题讨论】:

标签: c++ templates


【解决方案1】:

CommandBusFactory 的第一个模板参数本身就是一个模板。

然而,在main 中,你将Listener&lt;int,int,int,int&gt; 传递给它,这不是一个模板,而是一个类型。您需要一个类型模板参数。

然后,要从该类型中提取模板参数,您可以使用模板特化:

template
<
    class X,
    template <class, class, class, class> class Y
>
struct copy_template_params;

template
<
    template <class, class, class, class> class X,
    class A, class B, class C, class D,
    template <class, class, class, class> class Y
>
struct copy_template_params<X<A,B,C,D>,Y>
{
    using type = Y<A,B,C,D>;
};

template
<
    class ListenerType, 
    class CommandBusType = typename copy_template_params<ListenerType,CommandBus>::type
>
class CommandBusFactory
{
  public:
    static auto Get()
    {
        return CommandBusType{};
    }
};

【讨论】:

  • 您能否详细说明这是如何工作的?好像有点复杂。我看到您有一个接受类型 X 和模板模板类型的模板化结构。此外,您还有一个接受多种事物的专用版本。您能否更详细地解释发生了什么?例如,当我使用 CommandBusFactory>::Get(); 时会发生什么???
  • 我想批准这是正确的结果,但我仍然不完全理解这个答案。第二个模板结构是部分特化的吗?我不明白。
  • @GabrielGrigoras 我不知道该怎么解释。特化是第一个模板参数是具有 4 个参数的专用模板。 copy_template_params&lt;Listener&lt;int,int,int,int&gt;,CommandBus&gt;::type 扩展为 CommandBus&lt;int,int,int,int&gt;
  • 第一个模板类的目的是什么?
  • @GabrielGrigoras 将模板参数从Listener&lt;...&gt; 的特定专业化应用/复制到CommandBus&lt;...&gt;
【解决方案2】:

尚不完全清楚您在这里尝试什么。在那里使用模板将允许CommandBusFactory 为提供的ListenerType 创建不同的实例化,而不是让它们被传入,例如:

template <
    template<class T1, class T2, class T3, class T4> class ListenerType,
    class CommandBusType
>
class CommandBusFactory {
    static auto Get() {
        ListenerType<int, int, float, float> listener; // template params go here
        ListenerType<std::string, std::string, double, double> listener2; // allowing different ones
        return CommandBusType{};
    }
};
int main() {
    CommandBusFactory<Listener, SomeCommandBus> factory; // not here
}

如果您确实想预先提供ListenerType,然后从中确定CommandBusType,您可以使用typedef、返回值或类似方式(例如具有value_type 的容器等)。

template<class T1, class T2, class T3, class T4> class CommandBus {};
template<class T1, class T2, class T3, class T4> class Listener
{
public:
    typedef T1 t1;
    typedef T2 t2;
    typedef T3 t3;
    typedef T4 t4;
};
template <
    class ListenerType,
    class CommandBusType = CommandBus<typename ListenerType::t1, typename ListenerType::t2, typename ListenerType::t3, typename ListenerType::t4>
>
class CommandBusFactory {
    static auto Get() {
        return CommandBusType{};
    }
};

int main() {
    CommandBusFactory<Listener<int,int,float,float>> factory;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-06
    • 2016-11-09
    • 2018-07-04
    • 2018-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-15
    相关资源
    最近更新 更多