Преобразование типов при удержании шаблона функции - PullRequest
0 голосов
/ 08 сентября 2018

У меня есть шаблонная функция, которая генерирует объекты в соответствии с типом T своего аргумента. Похоже

 template<typename T>
 container<T> foo(T t)
 {
     return container<T> { item<T>{t} };
 }

где container - это класс шаблона, который содержит другой класс шаблона item.

Я реализовал operator+ для container<T>, чтобы контейнеры с одинаковыми базовыми типами T могли складываться.

Теперь я хочу, чтобы следующая строка работала

auto sum = foo("abc") + foo(std::string("def"));  // type mismatch

Другими словами, я хочу, чтобы foo генерировал container<const char *> всякий раз, когда он видит std::string, или наоборот.

Конечно, я могу явно перегрузить foo как

container<const char *> foo(std::string str)
{
    return container<const char *> { item<const char *> { str.c_str() } };
}

Но у меня так много функций, как foo, что я действительно не хочу писать перегруженную версию для каждой из них.

Это открытый вопрос дизайна. Любое решение, предложение или обходной путь приветствуются и приветствуются. Большое спасибо.

Ответы [ 3 ]

0 голосов
/ 08 сентября 2018

Я бы предложил использовать псевдоним типа шаблона:

template <typename T> using bar = std::conditional_t<std::is_same_v<T, const char *>, std::string, T>;

Тогда ваша функция становится:

template<typename T>
container<bar<T>> foo(T t)
{
    return container<bar<T>> { item<bar<T>>{t} };
}
0 голосов
/ 08 сентября 2018

Если вы думаете об этом, то поведение, которое вы ищете, кажется более специфичным для container<T> или container<std::string>, чем foo() и его братьев и сестер. Поэтому я думаю, что один из способов достижения вашей цели - перегрузить operator + хотя бы для случая container<std::string>, так что можно добавить не только контейнеры одного типа элемента, но вместо этого вы можете добавить любой контейнер типа элемента, который можно преобразовать в T (или просто std::string) в container<T> (или просто container<std::string>). Например, что-то вроде этого:

template <typename U>
container<std::string> operator +(container<std::string> a, const container<U>& b)
{
    a.insert(end(a), begin(b), end(b));
    return a;
}
0 голосов
/ 08 сентября 2018
#include <string>
using namespace std::string_literals;

и добавьте одну букву:

auto sum = foo("abc"s) + foo(std::string("def"));
//                  ^ here
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...