函数模板推导中的类型转换

时间:2018-09-08 13:56:05

标签: c++

我有一个模板函数,该函数根据其参数的类型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 :(得分:2)

我建议使用模板类型别名:

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} };
}

答案 1 :(得分:1)

如果您考虑一下,您寻求的行为似乎更具体 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;
}

答案 2 :(得分:-1)

auto sum = foo("abc"s) + foo(std::string("def"));
//                  ^ here

并添加一个字母:

{{1}}