【问题标题】:Function template specialization in C++, no Instance of overloaded functionC++中的函数模板特化,没有重载函数的实例
【发布时间】:2021-12-25 18:55:41
【问题描述】:

我正在学习 C++ 中的函数模板专业化,我的任务是编写一个名为 plus 的模板函数,它返回它可能是不同类型的两个参数的总和。一个按值接受的版本,另一个按指针接受的版本。作为一个额外的挑战,我被要求重载这个函数,以便它连接两个字符串。

template <typename T1, typename T2> decltype(auto) plus(const T1& a, const T2& b) {
    return a + b;
}

template <typename T1, typename T2> decltype(auto) plus(const T1* a, const T2* b) {
    return *a + *b;
}

// concatenate two strings
template <>
std::string_view plus<std::string_view, std::string_view> (std::string_view a, std::string_view b) {
    return std::string { a } + std::string{ b };
}

问题是我在连接两个字符串的函数的特化重载上遇到错误。我决定选择 std::string_view 而不是 std::string 的原因是,当使用字符串文字 (const char*) 调用函数时,它不会解析为接受 const * 的第二个定义,我猜这将是解决了std::string

所以我真的无法弄清楚发生了什么。只是一个疯狂的猜测,但这可能与我有两个不同的模板函数(称为 plus)有关,但它无法确定我正在尝试专门化/重载哪个模板函数?

更新:

问题似乎与模板解析有关。接受 const T* 的定义始终是任何字符串文字的首选。只是想找到解决办法。

【问题讨论】:

  • 模板是红鲱鱼。没有为字符串视图定义 + 运算符。在普通的非模板函数中你会遇到这个问题。
  • @RaymondChen 已修复,我的代码中的 std::string 构造函数只是粘贴了错误的定义。
  • @RaymondChen 我还尝试专门针对字符串文字使用const char*,但仍然是没有重载函数实例的问题。
  • 我已将问题缩小到函数负载分辨率。无论我如何专门化模板,它仍然更喜欢使用指针的第二个定义。

标签: c++ templates overload-resolution function-templates-overloading


【解决方案1】:

如果您可以使用 C++20,那么这可以通过概念轻松完成。

任何可转换为string_view 的东西,例如stringconst char*,都会被带到这个函数中:

template<typename T>
concept StringView = std::convertible_to<T, std::string_view>;

auto plus(StringView auto a, StringView auto b) 
{
    return std::string(a).append(b);
}

同样,您可以轻松定义其他概念,而只需排除StringView

template<typename T>
concept Reference = std::is_reference_v<T> && !StringView<T>;

template<typename T>
concept Pointer = std::is_pointer_v<T> && !StringView<T>;

auto plus(const Reference auto a, const Reference auto b)
{
  ⋮
  ⋮

【讨论】:

    【解决方案2】:

    这是我的建议:

    template <typename T1, typename T2, typename T3> T3 plus(const T1& a, const T2& b) {
        return a + b;
    }
    
    template <typename T1, typename T2, typename T3> T3 plus(const T1* a, const T2* b) {
        return *a + *b;
    }
    
    template <typename T1, typename T2, typename T3> T3 plus(T1 a, T2 b) {
        return a + b;
    }
    
    // concatenate two strings
    template <>
    std::string plus<std::string_view, std::string_view> (std::string_view a, std::string_view b) {
        return std::string(a).append(b);
    }
    

    由于字符串视图需要引用另一个字符串的内容,因此您需要返回一个字符串,因为新创建的 string_view 将指向一个临时对象。

    也没有办法将 2 个 string_view 连接在一起,因为将两个字符串连接在一起需要 string_view 能够保存对其他字符串视图的引用(因为它们本身不保存字符串内容)。

    此外,需要第三个类型名,因为此实现将返回另一种类型 (std::string),因为您不想返回临时的 string_view

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      • 2019-04-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多