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

C++临时对象指针作const char*模板参数报错及递归类型推导问题

编译失败问题复现

尝试将临时类对象的内部资源作为模板参数传入时编译失败,测试代码如下:

#include <iostream>

constexpr size_t size(const char* s)
{
    int i = 0;
    while(*s!=0) {
        ++i;
        ++s;
    }
    return i;
}

template <const char* S>
struct string_struct
{
    constexpr string_struct() {
        for (int i=0; i < size(S); ++i) {
            buf_[i] = S[i];
        }
    }
    constexpr const char* get() {
        return buf_;
    }
    char buf_[size(S)] = {0};
};

constexpr const char some_chars[] = "100";

constexpr auto compose_string()
{
    string_struct<some_chars> other_str{};
    return string_struct<other_str.get()>;
}

int main()
{
    compose_string();
}

GCC 12.1编译报错信息:

<source>: In function 'constexpr auto compose_string()':
<source>:32:41: error: 'other_str.string_struct<(& some_chars)>::get()' is not a valid template argument for 'const char*' because it is not the address of a variable
   32 |     return string_struct<other_str.get()>;
      |                                         ^
<source>:29:16: error: invalid return type 'auto' of 'constexpr' function 'constexpr auto compose_string()'
   29 | constexpr auto compose_string()
      |   

待解决问题:

  • 如何将string_struct实例的内部资源用于模板实例化?
  • 若方案可行,如何推导递归返回多层嵌套string_struct实例的函数的返回类型?该实现思路是否符合C++标准、具备可行性?

问题解答

原实现思路不可行的核心原因

C++标准对指针类型非类型模板参数有强制约束:仅指向静态存储期、具备内部/外部链接的对象的指针,可作为合法的非类型模板参数。
原代码中other_str.get()返回的是函数局部栈对象other_str的内部成员buf_的地址,属于自动存储期对象,地址随函数调用栈变化,完全不满足模板参数的要求,因此编译直接失败。不存在直接将局部对象内部缓冲区地址作为模板参数的方法,这是标准层面的硬限制。

符合标准的替代实现方案

放弃将字符串内容绑定到外部const char*模板参数的思路,改用C++20支持的类类型非类型模板参数(NTTP),直接将字符序列作为模板参数的一部分持有,无需依赖外部指针:

#include <array>
#include <cstddef>
#include <utility>

template<std::size_t N>
struct string_struct {
    std::array<char, N> buf{};

    constexpr string_struct() = default;
    // 从字符串字面量构造
    constexpr string_struct(const char (&s)[N]) {
        for (std::size_t i = 0; i < N; ++i) buf[i] = s[i];
    }
    // 拼接两个字符串的内部构造函数
    template<std::size_t M, std::size_t... Is, std::size_t... Js>
    constexpr string_struct(const string_struct<M>& a, const string_struct<N-M+1>& b,
                            std::index_sequence<Is...>, std::index_sequence<Js...>)
        : buf{a.buf[Is]..., b.buf[Js]..., '\0'} {}

    constexpr const char* get() const { return buf.data(); }
    constexpr std::size_t length() const { return N - 1; }
};

// 字符串字面量推导指引
template<std::size_t N>
string_struct(const char (&)[N]) -> string_struct<N>;

// 字符串拼接运算符重载
template<std::size_t N, std::size_t M>
constexpr auto operator+(const string_struct<N>& a, const string_struct<M>& b) {
    return string_struct<N + M - 1>(a, b,
        std::make_index_sequence<N-1>{},
        std::make_index_sequence<M-1>{});
}

// 递归拼接示例
constexpr auto compose_string() {
    constexpr string_struct s1{"100"};
    constexpr string_struct s2{"abc"};
    constexpr string_struct s3{"def"};
    // 多层嵌套拼接可在编译期完成,返回类型自动推导
    return s1 + s2 + s3;
}

#include <iostream>
int main() {
    constexpr auto res = compose_string();
    std::cout << res.get() << std::endl; // 输出:100abcdef
}

该实现完全符合C++20标准,无未定义行为:

  • 字符串内容直接存储为模板参数的一部分,不依赖外部静态存储的指针
  • 支持任意多层递归拼接、嵌套扩展
  • 所有操作可在constexpr上下文完成,编译期即可生成最终字符串结果

递归返回类型推导说明

C++14及以上版本中,constexpr函数使用auto作为返回值类型是合法语法。原代码中invalid return type 'auto'报错是前置的模板参数非法导致的连锁错误,并非auto本身的问题。
上述替代实现中,每一步拼接操作的返回值都是长度确定的string_struct<固定长度>实例,类型在编译期完全确定,编译器可自动推导返回类型,无需额外手动声明类型。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 13:15:47