模板无法自动将参数 `const char *` 转换为 `const std::string &`

编程语言 2026-07-07

在模板函数调用中,类型为 const char * 的实际参数通常会被自动转换为 const std::string &。但并非在所有情况下如此,我也不知道如何修复这些失败的情况。

我正在使用Debian trixie、GCC和 CMake,所有软件都已更新。也许这是一个与GCC相关的问题,但我不确定。

下面是一个一切正常工作的示例。

#include <iostream>
#include <format>
#include <string>

template<typename T>
void arg(const std::string & key, const T & value) noexcept {
    if constexpr (std::is_same_v<T, std::string>) {
        std::cerr << std::format("{}=\"{}\"", key, value);
    } else {
        std::cerr << std::format("{}={}", key, value);
    }
    std::cerr << std::endl;
}

int main(int argc, char **argv) {
    std::cout << "Hello, world! test:" << TEST << std::endl;

    arg("key", "value");
    arg("ans", 42);

    std::cout << "Goodby, world!" << std::endl;
    return 0;    
}

但在下一个案例中,添加了一个模板参数后,编译会失败,我也不知道原因,以及如何修复。添加的模板参数不是一个类型,而是一个模板常量,我无法弄清它是如何改变行为的。对模板实例化的第一次调用时的编译错误显示为:

error: no matching function for call to ‘arg(const char [4], const char [6])’
#include <iostream>
#include <format>
#include <string>

template<typename T, const char * SEP = ":">
void arg(const std::string & key, const T & value) noexcept {
    if constexpr (std::is_same_v<T, std::string>) {
        std::cerr << std::format("{}{}\"{}\"", key, SEP, value);
    } else {
        std::cerr << std::format("{}{}{}", key, SEP, value);
    }
    std::cerr << std::endl;
}

int main(int argc, char **argv) {
    std::cout << "Hello, world! test:" << TEST << std::endl;

    arg("key", "value"); // error: no matching function for call to ‘arg(const char [4], const char [6])’
    arg("ans", 42);

    std::cout << "Goodby, world!" << std::endl;
    return 0;    
}

我的问题是:

  • 第二个示例失败的原因是什么,我真的很想知道。
  • 如何修复第二个示例的行为?

此致,敬礼。

解决方案

问题并非出在 const char[6] 参数上。即使在工作版本中,T 也是 const char[6],字符数组也可以通过引用传递。这不是问题所在。

error: no matching function for call to ‘arg(const char [4], const char [6])’ 只是一个症状。为什么没有匹配的函数调用?请阅读完整的错误信息:

<source>: In function 'int main(int, char**)':
<source>:18:8: error: no matching function for call to 'arg(const char [4], const char [6])'
   18 |     arg("key", "value"); // error: no matching function for call to ‘arg(const char [4], const char [6])’
      |     ~~~^~~~~~~~~~~~~~~~
  • there is 1 candidate
    • candidate 1: 'template<class T, const char* SEP> void arg(const std::string&, const T&)'
      <source>:6:6:
          6 | void arg(const std::string & key, const T & value) noexcept {
            |      ^~~
      • template argument deduction/substitution failed:
        • error: '":"' is not a valid template argument for type 'const char*' because string literals can never be used in this context
          <source>:5:41:
              5 | template<typename T, const char * SEP = ":">
                |

错误信息指出

  • 没有匹配的函数调用
  • 有一个候选,但……
  • 因为……无法实例化
  • ":" 不是类型 const char* 的有效模板参数。见 temp.arg.nontype

最后一点才是实际的错误。

可能的修复方法是在分隔符处使用 char,然后 ':' 可以用作默认值(示例 由Oersted提供)。或者不要将 SEP 设为模板参数,而改为普通的函数参数。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章