代码之家  ›  专栏  ›  技术社区  ›  timmy george

当类具有非constexpr std::array时,如何将std::array.size()用作模板参数

  •  6
  • timmy george  · 技术社区  · 11 月前

    以下是一个玩具示例

    班级 student 有a std::array<char, 15> 打电话 name 以及一个整数 age 。学生有一个名为的成员函数 encode 调用全局模板函数 编码 使用 name.size() 作为模板参数。

    代码如下:

    //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

    3 回复  |  直到 11 月前
        1
  •  5
  •   Thomas Weller    11 月前

    我不喜欢包括 <tuple> 标题仅供使用 std::tuple_size_v .

    我想你也可以用

    return ::encode<decltype(name){}.size()>(age);
    
    • decltype(name) 为您提供类型,无需 this 指针
    • {} 创建实例
    • .size() 给出该实例的大小

    由于这是constexpr,因此在编译时计算结果为15,并且创建临时实例没有实际开销。

        2
  •  3
  •   NathanOliver    11 月前

    你可以得到的值 N 从数组中使用 std::tuple_size<std::array> 比如:

    unsigned long encode(){
        return ::encode<std::tuple_size_v<decltype(name)>>(age);
    }
    

    这可以在这里看到效果 live example .

        3
  •  2
  •   wohlstad    11 月前

    使用 name.size() 需要访问 this (并通过它成员 name )但由于这不是constexpr上下文,因此无法编译。

    相反,你应该使用 类型 std::array 名称 这已经暗示了尺寸。
    为此,您可以使用 std::tuple_size (它有一个专门的 std::数组 ),
    可能使用其辅助变量模板 std::tuple_size_v :

    unsigned long encode() {
        return ::encode<std::tuple_size_v<decltype(name)>>(age);
    }
    

    注意以下用法 decltype 要获取的类型 std::数组 从成员 名称 .