передача прямой строки в шаблон в c ++ - PullRequest
0 голосов
/ 29 августа 2018

C ++: передача строки в шаблоны.

Не указывая, какой тип данных int работает нормально, но когда мы передаем строку в шаблон, мы сталкиваемся с ошибкой, не могли бы вы помочь мне в этом вопросе.

template <Typename T>
T add(T a,T b)
{
    return a+b;
}

int main() {
    int    res = add(2,5);  // this is execute perfctly.
    string str = add("hello","world"); // here i am getting eror for passing directly string, can we fix this issue without specifying what data type we are passing.
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Чтобы сделать это чистым и избежать необходимости указывать типы на сайте вызова, сначала нужно отключить шаблон 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

0 голосов
/ 29 августа 2018

Я предполагаю, что вы думаете, что вы передаете std::string на add, но это не так. Вы проходите const char *. Вы не можете вызвать + с двумя символьными указателями.

Если вместо этого вы передадите две строки std ::, вы можете вызвать + с ними.

#include <string>

using namespace std::string_literals;

template <typename T>
T add(T a,T b)
{
    return a+b;
}

int main() {
    int    res = add(2,5);  // this is execute perfctly.
    std::string str = add("hello"s,"world"s);  // the s on the end makes it a std::string.  

    // this is the same as the line above
    std::string str2 = add(std::string("hello"), std::string("world"));
    return 0;
}

https://godbolt.org/z/kSqs2l

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...