在 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
,还是仍然取决于输入(例如,对于char
或short
,您希望返回为@987654328 @,对于int
或long
,您希望它返回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<double>::type
只是 double
等 - 但你可以将 calc_return<int>::type
专门化为你想要的任何东西。
为什么要这样做而不只是template <class T, class RetT>
并通过模板参数列表指定返回类型?
@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 ... ->
部分意味着我稍后会声明返回类型(我这样做是因为它依赖于number
)。 decltype
是“声明类型”,即表达式 number/10.0
的类型。显然这取决于T number
。特别是,这意味着 return 语句中没有隐式转换,因为返回类型与返回表达式完全匹配。如果您的编译器是全新的(C++14 标准),您实际上不需要 -> decltype()
部分。【参考方案3】:
你的意思是这样的:
template <class T, class T1>
T1 divide(T number)
return ((T1)number) / 10;
....
double res = divide<int, double>(2);
【讨论】:
这对我不起作用,编译器正在寻找带有两个变量的函数头。它应该有一个并返回一个(但返回可能不同) @YelizavetaYR 你说它不起作用是什么意思?divide<int, double>(....)
实例化/调用具有int
类型参数和double
类型结果的函数。
当我尝试运行此代码时 - 对函数的调用看起来像 divide(x);
并且编译器会抛出一个错误,告诉我我的参数不匹配 - 我只传递了一个但询问两个要退回。问题是我们只想传递一个参数并有一个不同类型的返回值。抱歉,如果我的问题不清楚,我并不是有意引起混淆。
@YelizavetaYR 是的,如果你调用divide(x)
,编译器无法实例化函数。但是如果你调用divide<double,int>(x)
,编译器应该会很高兴。以上是关于在 C++ 中,如何将返回值模板化为与参数值不同?的主要内容,如果未能解决你的问题,请参考以下文章