C++ 中的函数模板特化,没有重载函数的实例
Function template specialization in C++, no Instance of overloaded function
我正在学习 C++ 中的函数模板专业化,我的任务是编写一个名为 plus
的模板函数,returns 它是两个可能不同类型的参数的总和。一个版本按值接受,另一个版本按指针接受。作为一个额外的挑战,我被要求重载这个函数,以便它连接两个字符串。
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*
) 调用函数时,它不会解析为接受 [=15= 的第二个定义] 我猜这会在 std::string
.
上得到解决
所以我真的不知道发生了什么。只是一个疯狂的猜测,但这可能与我有两个不同的模板函数有关 plus
并且它无法弄清楚我正在尝试专门化/重载哪个?
更新:
问题似乎与模板解析有关。接受 const T*
的定义始终是任何字符串文字的首选。只是想找到解决办法。
这是我的建议:
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);
}
由于字符串视图需要引用另一个字符串的内容,因此您需要 return 一个字符串,因为新创建的 string_view 将指向一个临时对象。
也没有办法将 2 个 string_view 连接在一起,因为将两个字符串连接在一起需要 string_view 能够保存对其他字符串视图的引用(因为它们不t 自己保存字符串内容)。
此外,第三个类型名是必需的,因为此实现将 return 另一种类型 (std::string),因为您不想 return 临时的 string_view
如果您可以访问 C++20,那么这可以通过概念轻松完成。
任何可转换为 string_view
的内容,例如 string
和 const 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)
{
⋮
⋮
我正在学习 C++ 中的函数模板专业化,我的任务是编写一个名为 plus
的模板函数,returns 它是两个可能不同类型的参数的总和。一个版本按值接受,另一个版本按指针接受。作为一个额外的挑战,我被要求重载这个函数,以便它连接两个字符串。
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*
) 调用函数时,它不会解析为接受 [=15= 的第二个定义] 我猜这会在 std::string
.
所以我真的不知道发生了什么。只是一个疯狂的猜测,但这可能与我有两个不同的模板函数有关 plus
并且它无法弄清楚我正在尝试专门化/重载哪个?
更新:
问题似乎与模板解析有关。接受 const T*
的定义始终是任何字符串文字的首选。只是想找到解决办法。
这是我的建议:
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);
}
由于字符串视图需要引用另一个字符串的内容,因此您需要 return 一个字符串,因为新创建的 string_view 将指向一个临时对象。
也没有办法将 2 个 string_view 连接在一起,因为将两个字符串连接在一起需要 string_view 能够保存对其他字符串视图的引用(因为它们不t 自己保存字符串内容)。
此外,第三个类型名是必需的,因为此实现将 return 另一种类型 (std::string),因为您不想 return 临时的 string_view
如果您可以访问 C++20,那么这可以通过概念轻松完成。
任何可转换为 string_view
的内容,例如 string
和 const 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)
{
⋮
⋮