【问题标题】:Is it impossible to specialize non-static members in a class template? Why?在类模板中专门化非静态成员是不可能的吗?为什么?
【发布时间】:2021-08-24 14:31:45
【问题描述】:

背景

我有一个类,我已经模板化了通过继承获得编译时多态性作为运行时多态性的替代方案。

我对这个类中的一些方法有两种不同的特化。我们称他们为T_aT_b

问题

我想根据模板参数用不同的值初始化这个类的一个常量但非静态的对象数组。

template<class T>
class A {
    const anotherObject& aO;
    const ConfigPar configPars[];
}

无效尝试

专业化

首先,我认为我可以专门化成员:

template<class T>
class A {
    const ConfigPar configPars[];

    A(T t);
}

template<>
const ConfigPar A<T_a>::configPars[] {
        {anotherObject.foo1, "bar1"},
        {anotherObject.foo2, "bar2"},
}

template<>
const ConfigPar A<T_b>::configPars[] {
        {anotherObject.foo1, "bar1"},
        {anotherObject.foo2, "bar2"},
        {anotherObject.foo3, "bar3"},
}

但是,这不起作用,因为显然您只能专门化静态类成员。但是,configPars 数组中对象的值依赖于另一个实例成员,所以我不能将configPars 设为静态。

构造函数重载

接下来,我想重载A的构造函数,只是在构造函数中以不同的方式初始化configPars

template<class T>
class A {
    const ConfigPar configPars[];

    A(T_a t) : configPars{
            {anotherObject.foo1, "bar1"},
            {anotherObject.foo2, "bar2"},
    } {}

    A(T_b t) : configPars{
            {anotherObject.foo1, "bar1"},
            {anotherObject.foo2, "bar2"},
            {anotherObject.foo3, "bar3"},
    } {}
}

但是,在此我的编译器抱怨error: too many initializers for 'const ConfigPar [0]'。显然我不能在声明中忽略数组的大小?

问题在于两个特化(或重载的构造函数,在这种情况下)之间的数组大小不同。

我该如何处理?

【问题讨论】:

  • const ConfigPar configPars[]; 不合法。所有类成员都必须具有定义的大小,这意味着数组大小必须在类定义中已知。您可以使用 const std::vector&lt;ConfigPar&gt; 代替它。
  • @NathanOliver 我明白了。是否无法根据模板参数定义大小,例如在专业?这是嵌入式的(在微控制器上运行),所以很遗憾我无法访问标准库的 std:: 容器。

标签: c++ templates


【解决方案1】:

在类定义中必须知道所有类成员的大小。这包括数组成员的大小。您可以做的是根据 T 是什么来确定您拥有的数组大小,并在定义中提供它。可能看起来像

template<class T>
class A {
    const ConfigPar configPars[(std::is_same_v<T, T_a> ? 2 : 3)]; // 2 for T_a, 3 otherwise

    A(T t);
};

// specialization of constructor for T_a
template<>
A<T_a>::A(T_a t) : configPars{
        {1, "bar1"},
        {2, "bar2"},
}
{
    // constructor body, use t here
}

// specialization of constructor for T_b
template<>
A<T_b>::A(T_b t) : configPars{
        {1, "bar1"},
        {2, "bar2"},
        {3, "bar3"},
}
{
    // constructor body, use t here
}

【讨论】:

  • 这是一个优雅的解决方案,但是,这是嵌入的,所以很遗憾type_traits 对我不可用。 (对不起,忘了在我的问题中提及)
  • @Compizfox 好消息是,您不需要它们。 std::is_same 自己很容易实现。您甚至可以从 here 复制一个实现。
猜你喜欢
  • 1970-01-01
  • 2011-01-21
  • 2018-11-16
  • 2017-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多