You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

类含非constexpr std::array时,如何将std::array.size()作为模板参数?

C++编译错误:模板参数中使用std::array::size()的问题

类student包含一个名为name的std::array<char, 15>成员和一个整数age。该类的成员函数encode尝试以name.size()作为模板参数调用全局模板函数encode。

代码示例

//main.cpp
#include <iostream>
#include <array>

template <unsigned long num1>
unsigned long encode(unsigned long num2){
    return num1 + num2;
}


struct student {
    std::array<char, 15> name;
    int age;
    student(const std::array<char, 15>& name, int age):
        name(name),
        age(age)
    {}
    unsigned long encode(){
        return ::encode<name.size()>(age);
    }
};

int main(){
    std::array<char, 15> name = {"Tim"};
    student Tim(name, 17);
    std::cout << Tim.encode();
}

编译错误信息

>g++ main.cpp -std=c++11

main.cpp: In member function 'long unsigned int student::encode()':
main.cpp:22:43: error: use of 'this' in a constant expression
   22 |                 return ::encode<name.size()>(age);
      |                                           ^
main.cpp:22:45: error: no matching function for call to 'encode<((student*)this)->student::name.std::array<char, 15>::size()>(int&)' 
   22 |                 return ::encode<name.size()>(age);
      |                        ~~~~~~~~~~~~~~~~~~~~~^~~~~
main.cpp:9:15: note: candidate: 'template<long unsigned int num1> long unsigned int encode(long unsigned int)'
    9 | unsigned long encode(unsigned long num2){
      |               ^~~~~~
main.cpp:9:15: note:   template argument deduction/substitution failed:
main.cpp:22:45: error: use of 'this' in a constant expression
   22 |                 return ::encode<name.size()>(age);
      |                        ~~~~~~~~~~~~~~~~~~~~~^~~~~
main.cpp:22:42: note: in template argument for type 'long unsigned int'
   22 |                 return ::encode<name.size()>(age);

用户疑问

是否必须使用::encode<15>(age)来解决此问题?因为我认为std::array的一大优势是能携带自身大小,无需额外存储或硬编码大小。

g++ version: 14.1.0


问题原因

模板参数必须是编译期常量表达式。虽然std::array::size()在C++11及以后是constexpr函数,但在类的非静态成员函数中,访问成员变量name需要依赖this指针,而this不属于编译期常量,因此name.size()无法直接作为模板参数传递。

无需硬编码的解决方案

你可以通过以下几种方式避免硬编码大小:

  1. 利用std::array的编译期静态常量
    std::array自带编译期可用的静态size成员,或者通过std::tuple_size获取大小,在成员函数中这样写:

    unsigned long encode(){
        // 方式1:直接引用std::array的静态size
        return ::encode<decltype(name)::size()>(age);
        // 方式2:用std::tuple_size获取
        // return ::encode<std::tuple_size<decltype(name)>::value>(age);
    }
    
  2. 将类模板化,让大小成为模板参数
    如果希望student类适配不同大小的std::array,可以把类定义为模板:

    template <std::size_t N>
    struct student {
        std::array<char, N> name;
        int age;
        student(const std::array<char, N>& name, int age):
            name(name), age(age) {}
        unsigned long encode(){
            return ::encode<N>(age);
        }
    };
    
    int main(){
        std::array<char, 15> name = {"Tim"};
        student<15> Tim(name, 17);
        std::cout << Tim.encode();
    }
    

    这种方式既避免了硬编码,还让类具备了通用性。

  3. C++20及以后:constexpr成员函数
    升级到C++20后,可以将成员函数声明为constexpr,此时this在constexpr上下文中是编译期常量,就能直接使用name.size():

    constexpr unsigned long encode() const {
        return ::encode<name.size()>(age);
    }
    

总结

不需要硬编码15,通过上述方法就能利用std::array的编译期大小信息,同时满足模板参数的常量表达式要求。

内容的提问来源于stack exchange,提问作者timmy george

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 06:54:58