c++ - 为什么我不能在这个专门的函数模板中将字符串文字传递给 const char* const&

标签 c++ pointers string-literals

为什么在专用函数模板中将字符串文字传递给 const char* const& 是非法的,而传递给 const char* 是合法的?

事情是这样的。 C++ Primer中有两个关于模板特化的练习:

Exercise 16.63: Define a function template to count the number of occurrences of a given value in a vector. Test your program by passing it a vector of doubles, a vector of ints, and a vector of strings.

Exercise 16.64: Write a specialized version of the template from the previous exercise to handle vector<const char*> and a program that uses this specialization.

下面的代码是我的答案,当我将字符串文字传递给这个专门的 count 函数时出现编译错误。

// Count the number of occurrences of a given value in a vector
template <typename T>
std::size_t count(const std::vector<T>& vec, const T& value)
{
    std::size_t i = 0;
    for (const auto& v : vec) {
        if (v == value)
            ++i;
    }
    return i;
}

// A specialized version where T = const char*
template <>
std::size_t count(const std::vector<const char*>& vec, const char* const& value)
{
    std::size_t i = 0;
    for (const auto& v : vec) {
        if (!strcmp(v, value))
            ++i;
    }
    return i;
}

int main()
{
    std::vector<const char*> sVec{ "cpp", "primer", "cpp", "fifth", "edition", "Cpp", "cpp" };
    
    // Error message: no instance of function template "count" matches the argument list, 
    // argument types are: (std::vector<const char *, std::allocator<const char *>>, const char [4])
    std::cout << count(sVec, "cpp") << std::endl;

    return 0;
}

此外,在非模板函数中将字符串文字传递给 const char* const& 是完全可以的,这让我很困惑。

void test(const char* const& str)
{
    std::cout << str << std::endl;
}

int main()
{
    test("cpp"); // Prints "cpp" as expected
    return 0;
}

最佳答案

您不会“传递给函数模板特化”。该调用是根据原始模板定义推导出来的(不管任何特化),如果成功则推导出一个类型。然后,如果推导类型存在专门化,则将调用它。

错误消息是关于类型推导失败的。即使您删除了特化,您也应该会看到完全相同的错误。

类型推导失败因为T出现在两个不同的参数中,但每个参数的推导结果不同:

  • 推导 vector<T>& vec反对vector<const char *>生产 T=const char *
  • 推导 const T& value反对"cpp"生产 T=const char[4] .

只有在 T 的所有实例中,推导才会成功被推导产生相同的类型。没有通过考虑可用的转换来协调不同类型的额外步骤。

解决该问题的一种方法是使用重载而不是特化(即删除文本 template <> )。然后是一个由非模板函数和推导结果(如果有)组成的重载集。如果演绎失败,就像它那样,这不是错误,因为重载集仍然包含一些东西。

关于c++ - 为什么我不能在这个专门的函数模板中将字符串文字传递给 const char* const&,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71047430/

相关文章:

c++ - 在变量中存储基本算术运算符

c++ - 将线近似为平面图轮廓

c - 带空指针的动态数组

string - 生命周期如何作用于常量字符串/字符串文字?

c - 避免在 printf 周围的包装器中发出警告

无法将字符串文字分配给 C 中的字符数组

c++ - 我如何在 C++ 中定义 24 位数组?

c++ - 使用 gcc/g++ 编译器编译 c++

c - 第一次创建Stack。一行打印两次。为什么?

c - int 指针类型转换失败