【问题标题】:Type-dependent constant in template function模板函数中依赖于类型的常量
【发布时间】:2015-04-11 09:09:50
【问题描述】:

我想要一个模板化函数中的静态数组,其长度取决于函数专用的类型。我的第一次尝试是:

标题:

template<typename T>
struct Length {
    const static size_t len;
};

template<typename T>
void func(){
  static T vars[Length<T>::len]; // len not const. according to compiler!
  // ...
}

源文件:

template<> const size_t Length<double>::len = 2;
template<> const size_t Length<float>::len = 1;
// ...

但是,g++ 没有编译这个并抱怨

错误:“vars”的存储大小不是恒定的

那么,这里到底有什么问题呢?我知道固定长度数组的大小需要是一个常数并且在编译时已知,但这里似乎就是这种情况。 当我写作时

const size_t len = 2;

void func(){
    static double vars[len];
}

它编译没有问题。

问题:

代码有什么问题,有哪些替代方法可以实现所需的行为?我不想在运行时分配内存...

【问题讨论】:

    标签: c++ arrays templates template-specialization


    【解决方案1】:

    要使const 变量被视为编译时常量(正式地,常量表达式),它的值必须在使用时可用。这意味着专门的定义必须转到头文件。

    如果只是作为成员的专业化完成,就像你所做的那样,我相信这会给你一个多重定义错误。您应该对整个类模板进行专门化,并保持静态成员定义内联:

    template<typename T>
    struct Length;
    
    template <>
    struct Length<double>
    {
      static const size_t len = 2;
    };
    

    附带说明,您的程序最初是无效的:必须在使用前声明显式特化。这意味着您必须至少在标题(或您打算使用它的任何地方)中声明len 的特化。

    【讨论】:

    • 专门化类模板的模式称为元函数。这里绝对是正确的解决方案。
    • 成员的显式特化不需要事先声明。它将匹配其包含的类模板的成员声明。
    • @Potatoswatter 我不认为这是一个元函数。根据Boost.MPL,“metafunction 是一个类或类模板,表示在编译时可调用的函数。”
    • @Potatoswatter C++11 14.7.3/6:“如果模板、成员模板或类模板的成员被明确特化,则该特化应为在第一次使用该特化之前声明,这将导致在发生这种使用的每个翻译单元中发生隐式实例化;不需要诊断。” (我的)
    • (第一个线程):是的,这正是我们所拥有的:一个将类型映射到值的函数。
    【解决方案2】:

    下面的代码可以用g++ 4.6.3 很好地编译并产生输出

    2
    1
    

    array.cpp:

    #include <cstddef>
    #include <iostream>
    
    template<typename T>
    struct Length {
        const static size_t len;
    };
    
    template<typename T>
    void func(){
      static T vars[Length<T>::len]; 
      std::cout << (sizeof(vars) / sizeof(*vars)) << std::endl;
    }
    
    template<> const size_t Length<double>::len = 2;
    template<> const size_t Length<float>::len = 1;
    
    int main(){
      func<double>();
      func<float>();
    }
    
    $ make array
    g++     array.cpp   -o array
    $ ./array 
    2
    1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-17
      • 2022-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多