在 C++ 中,如何将返回值模板化为与参数值不同?

Posted

技术标签:

【中文标题】在 C++ 中,如何将返回值模板化为与参数值不同?【英文标题】:In C++ How do I template the return value to be unique from the parameter value? 【发布时间】:2015-01-08 17:01:36 【问题描述】:

我的代码如下所示 - 现在如果数字的数据类型是 int 输入,我希望它作为双输出。

template <class T>
T divide(T number)
 
    return number/10;
 

我主要有这个

 divide(5);
 divide(2.5);

在 2.5 的情况下,输入和输出的值将是 double 类型,因此没有问题,但在 5 的情况下,它作为 int 输入,但我需要它不被截断并以 double 类型返回.

template <class T, Class T1>
T1 divide(T number)
 
    return number/10;
 

这不起作用,因为它在函数中寻找两个参数。

T1 template <class T>
T1 divide(T number)
 
    return number/10;
 

这没有给我存储类或类型说明符的声明 - 当我在 T1 之前将单词 class 添加到该行时,我收到错误消息:函数返回不完整的类型。

【问题讨论】:

返回是总是 double,还是仍然取决于输入(例如,对于charshort,您希望返回为@987654328 @,对于intlong,您希望它返回double 它并不总是双重的,这就是我想将它模板化的原因。我想返回最适合指定数据类型的数据。 因此,您需要确定(并告诉我们)究竟什么最适合任何给定的输入类型。为了帮助您,我们需要知道您想要什么结果以及如何根据输入确定结果。 @JerryCoffin 这就是我的问题所在 - 输入类型可以是任何数值(甚至可能是字符)。但是输出类型,返回类型在某些情况下是不同的。特别是 int vs. double 或 int vs float 等。模板的想法是任何数值都可以输入,但可以返回不同的值。 使用模板,您可以构建从输入类型到输出类型的映射。但是,就像任何编程一样,您必须决定该映射应该是什么。编译器可以做你告诉它的事情,但你仍然需要告诉它你想要什么(现在,在我看来,你甚至不真正知道你想要什么)。跨度> 【参考方案1】:

最通用的方法是有一个帮助模板

template <typename T>
struct calc_return 
  using type = T;
;

template <class T>
typename calc_return<T>::type divide(T number)

   return number/10;

现在,如果规则有例外,您可以使用任何您喜欢的逻辑来专门化 calc_return

// Prior to the declaration of divide()
template <>
struct calc_return<int> 
  using type = double;
;

【讨论】:

老实说,我不是 100% 确定,我了解这里正在做什么。 这个想法是 calc_return&lt;double&gt;::type 只是 double 等 - 但你可以将 calc_return&lt;int&gt;::type 专门化为你想要的任何东西。 为什么要这样做而不只是template &lt;class T, class RetT&gt; 并通过模板参数列表指定返回类型? @OleksijPlotnyc'kyj :因为目的是将返回类型指定为模板的作者,而不是用户。 (想想图书馆)【参考方案2】:

在这种情况下,我认为你想要

template <class T>
auto divide(T number) -> decltype(number/10.0)

   return number/10.0;

如果您至少除以 10.0 而不是 10,编译器会很清楚返回类型应该是什么。

或 C++14 风格:

template <class T>
auto divide(T number) // Compiler will figure it out from the return statement.

   return number/10.0;

【讨论】:

decltype 指定返回一个类型?是指针吗?我不确定这是如何工作的。这基本上是说auto 将是指针返回的任何内容吗?这是否意味着函数的内容必须跟在括号中的decltype 后面? auto ... -&gt; 部分意味着我稍后会声明返回类型(我这样做是因为它依赖于number)。 decltype 是“声明类型”,即表达式 number/10.0 的类型。显然这取决于T number。特别是,这意味着 return 语句中没有隐式转换,因为返回类型与返回表达式完全匹配。如果您的编译器是全新的(C++14 标准),您实际上不需要 -&gt; decltype() 部分。【参考方案3】:

你的意思是这样的:

template <class T, class T1>
T1 divide(T number)

    return ((T1)number) / 10;


....

double res = divide<int, double>(2);

【讨论】:

这对我不起作用,编译器正在寻找带有两个变量的函数头。它应该有一个并返回一个(但返回可能不同) @YelizavetaYR 你说它不起作用是什么意思? divide&lt;int, double&gt;(....) 实例化/调用具有int 类型参数和double 类型结果的函数。 当我尝试运行此代码时 - 对函数的调用看起来像 divide(x); 并且编译器会抛出一个错误,告诉我我的参数不匹配 - 我只传递了一个但询问两个要退回。问题是我们只想传递一个参数并有一个不同类型的返回值。抱歉,如果我的问题不清楚,我并不是有意引起混淆。 @YelizavetaYR 是的,如果你调用divide(x),编译器无法实例化函数。但是如果你调用divide&lt;double,int&gt;(x),编译器应该会很高兴。

以上是关于在 C++ 中,如何将返回值模板化为与参数值不同?的主要内容,如果未能解决你的问题,请参考以下文章

C++模板详解

C++ 模板详解(转)

C++模板

如何将右值引用参数传递给 C++ 中的模板 operator() 函数?

如何将静态数组初始化为 C++ 函数中的某个值?

C++模板简介