Чтобы сделать это чистым и избежать необходимости указывать типы на сайте вызова, сначала нужно отключить шаблон add
для типов, которые не поддерживают operator+
, а затем обеспечить перегрузку для этих типов.
Сначала отключите добавление для const char*
...
template <typename T>
auto add(T a,T b) -> decltype(a + b)
{
return a+b;
}
Тогда обеспечьте перегрузку.
C ++ 17 way:
std::string add(std::string_view l, std::string_view r)
{
auto result = std::string(l);
result += r;
return result;
}
или c ++ 14 way:
std::string add(const char* l, const char* r)
{
auto result = std::string(l);
result += r;
return result;
}
Обратите внимание, что, несмотря на то, что это устраняет вашу ошибку компиляции, это ни в коем случае не является полным решением проблемы.
Рассмотрим:
str = add("hello",6);
Это фактически вернет указатель за конец строки, на который ссылается левый аргумент. Это потому, что (const char* p) + (int n)
приводит к адресу p + (sizeof(*p) * n)
.
Вам нужно будет добавить яд в объявления шаблона, чтобы отключить этот случай.
Вот более полное обращение:
#include <string>
#include <string_view>
#include <iostream>
template <typename L, typename R,
std::enable_if_t
<
!( std::is_pointer_v<std::decay_t<L>>
|| std::is_pointer_v<std::decay_t<R>>)
>* = nullptr>
auto add(L a, R b) -> decltype(a + b)
{
return a + b;
}
std::string add(std::string_view l, std::string_view r)
{
auto result = std::string(l);
result += r;
return result;
}
template<class R>
auto add(std::string_view l, R&& r)
-> decltype(std::to_string(std::forward<R>(r)))
{
auto result = std::string(l);
result += std::to_string(std::forward<R>(r));
return result;
}
template<class L>
auto add(L&& l, std::string_view r)
-> decltype(std::to_string(std::forward<L>(l)))
{
auto result = std::to_string(std::forward<L>(l));
result += r;
return result;
}
int main() {
using namespace std::literals;
auto emit = [](auto&& x) { std::cout << x << std::endl; };
emit(add(2,5));
emit(add("hello","world"));
emit(add("hello"s,"world"));
emit(add("hello"s,"world"));
emit(add("hello",6));
emit(add(6, "hello"));
return 0;
}
Ожидаемый результат:
7
helloworld
helloworld
helloworld
hello6
6hello
http://coliru.stacked -crooked.com / а / a3b217ee301b3a74