繁体   English   中英

返回具有不同模板参数值的不同类型(但相同类型)

[英]Return different types with different template parameter value (but same type)

我想要做的是定义3个这样的函数:

template<int t = 0> int test() { return 8; }
template<int t = 1> float test() { return 8.8; }
template<int t = 2> std::string test() { return "8.9"; }

int main()
{
    int a = test<0>();
    float b = test<1>();
    std::string c = test<2>();
    return 0;
}

它们使用相同类型的模板参数,但返回不同的类型。

我相信必须有一些方法可以做到这一点(比如std::get<>()就可以了),但我找不到怎么做。

它看起来像你在功能模板专业化之后。 需要为每个呼叫提供不同的实现符合要求。 然而,有一点需要注意,即专业化可能不会改变专用主模板的签名,只会改变实现。 这意味着我们不能这样做

template<int t> int test(); // Primary
template<> int test<0>() { return 8; } // OK, signature matches
template<> float test<1>() { return 8.8; } // ERROR

但我们还没有敬酒。 专业化的签名必须与主要为特定参数获得的签名相匹配。 因此,如果我们使返回类型依赖于模板参数,并解析为正确的类型,我们可以很好地定义我们的特化。

template<int t> auto test() -> /* Magic involving t that resolves to int, float, string */;
template<> int test<0>() { return 8; }
template<> float test<1>() { return 8.8; }
template<> std::string test<2>() { return "8.9"; }

这样的事情存在吗? 是的,你暗示了它。 我们可以使用std::tuple 它有一个std::tuple_element实用程序,可以将整数映射到一个类型序列(元组的元素)。 有了一个小帮手,我们可以构建我们的代码,以您希望的方式工作:

using types = std::tuple<int, float, std::string>;

template<int t> auto test() -> std::tuple_element_t<t, types>;

template<> int test<0>() { return 8; }
template<> float test<1>() { return 8.8; }
template<> std::string test<2>() { return "8.9"; }

现在,每个专业化都会匹配主要最终的签名。 所以我们得到了编译器的批准。

现场观看

@StoryTeller@ formerlyknownas_463035818提供了一个解释良好的模板专业化方法。 或者,可以使用if-constexprdecltype(auto)返回将三个函数组合成一个函数。

#include <iostream>
#include <string>
#include <cstring>
using namespace std::literals;

template<int t>
constexpr decltype(auto) test() noexcept
{
    if constexpr (t == 0) return 8;
    else if constexpr (t == 1) return 8.8f;
    else if constexpr (t == 2) return "8.9"s;
}

见在线直播

您声明了相同的模板3次,而您实际上想要专业化。 据我所知,你不能直接专注于返回类型(*)。 但是,没有什么是通过额外的间接层无法解决的。 您可以按照以下方式执行以下操作:

#include <string>

template <int> struct return_type_tag {};
template <> struct return_type_tag<0> { using type = int; };
template <> struct return_type_tag<1> { using type = float; };
template <> struct return_type_tag<2> { using type = std::string; };

template <int x> typename return_type_tag<x>::type test();

template<> int test<0>() { return 8; }
template<> float test<1>() { return 8.8; }
template<> std::string test<2>() { return "8.9"; }

int main()
{
    int a = test<0>();
    float b = test<1>();
    std::string c = test<2>();

    return 0;
}

(*)实际上你可以通过一个小技巧看到这个答案 我的方法的唯一好处是它已经在pre-c ++ 11中运行了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM