Tengo una función de plantilla, que genera objetos de acuerdo con el tipo T de su argumento. Parece que

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

Donde container es una clase de plantilla que contiene otra clase de plantilla item.

Implementé operator+ para container<T> para que los contenedores que tienen los mismos tipos subyacentes T puedan sumarse.

Ahora quiero que la siguiente línea funcione

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

En otras palabras, quiero que foo genere un container<const char *> cada vez que vea un std::string, o al revés.

Por supuesto, puedo sobrecargar explícitamente foo como

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

Pero tengo tantas funciones como foo que realmente no quiero escribir una versión sobrecargada para cada una de ellas.

Esta es una pregunta de diseño abierta. Cualquier solución, sugerencia o solución es bienvenida y apreciada. Muchas gracias.

c++
0
aafulei 8 sep. 2018 a las 16:56

3 respuestas

La mejor respuesta

Sugeriría usar un alias de tipo de plantilla:

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

Entonces su función se convierte en:

template<typename T>
container<bar<T>> foo(T t)
{
    return container<bar<T>> { item<bar<T>>{t} };
}
1
HolyBlackCat 8 sep. 2018 a las 14:01

Si lo piensa, el comportamiento que busca parece ser más específico para container<T> o container<std::string> que a foo() y sus hermanos. Así que supongo que una forma de lograr su objetivo sería sobrecargar operator + al menos para el caso container<std::string> de modo que no solo se puedan agregar contenedores del mismo tipo de elemento, sino que también se puede agregar cualquier contenedor de un tipo de elemento que se puede convertir a T (o simplemente std::string) a container<T> (o simplemente container<std::string>). Por ejemplo, algo parecido a esto:

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;
}
1
Michael Kenzel 8 sep. 2018 a las 14:08
#include <string>
using namespace std::string_literals;

Y agrega una letra:

auto sum = foo("abc"s) + foo(std::string("def"));
//                  ^ here
-1
Swordfish 8 sep. 2018 a las 13:59