C++ 不带<>调用模板函数;类型推断

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2833730/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:12:59  来源:igfitidea点击:

Calling template function without <>; type inference

c++templatestypesinference

提问by OlimilOops

If I have a function template with typename T, where the compiler can set the type by itself, I do not have to write the type explicitly when I call the function like:

如果我有一个带有 的函数模板typename T,编译器可以在其中自行设置类型,则在调用函数时我不必显式编写类型,例如:

template < typename T > 
T min( T v1, T v2 ) {
   return ( v1 < v2 ) ? v1: v2;
}
int i1 = 1, i2 = 2; int i3 = min( i1, i2 ); //no explicit <type> 

But if I have a function template with two different typenames like:

但是,如果我有一个具有两个不同类型名称的函数模板,例如:

template < typename TOut, typename TIn >
TOut round( TIn v ) {
   return (TOut)( v + 0.5 );
}
double d = 1.54;
int i = round<int>(d); //explicit <int>

Is it true that I always have to specify at least 1 typename? I assume the reason is because C++ can not distinguish functions between different return types.

我总是必须至少指定 1 个类型名,这是真的吗?我假设原因是因为 C++ 无法区分不同返回类型之间的函数。

But if I use a void function and handover a reference, again I must not explicitly specify the return typename:

但是,如果我使用 void 函数并切换引用,我也不能明确指定返回类型名:

template < typename TOut, typename TIn > 
void round( TOut & vret, TIn vin ) {
   vret = (TOut)(vin + 0.5);
}
   double d = 1.54;
   int i; round(i, d); //no explicit <int>

Should the conclusion be to avoid functions with return and more prefer voidfunctions that return via a reference when writing templates? Or is there a possibility to avoid explicitly writing the return type? Something like "type inference" for templates. Is "type inference" possible in C++0x?

结论应该是避免带返回的void函数,更喜欢在编写模板时通过引用返回的函数吗?或者是否有可能避免显式编写返回类型?类似于模板的“类型推断”。在 C++0x 中可以进行“类型推断”吗?

回答by Thomas

Overload resolution is done only based on function arguments; the return value is not used at all. If the return type cannot be determined based on the arguments, you will have to specify it explicitly.

重载解析仅基于函数参数完成;根本不使用返回值。如果无法根据参数确定返回类型,则必须明确指定。

I would not go down the path of "returning" a value through a reference parameter; that makes the calling code unclear. For example, I'd prefer this:

我不会走通过引用参数“返回”值的路径;这使得调用代码不清楚。例如,我更喜欢这个:

double x = round<double>(y);

over this:

在这个:

double x;
round(x, y);

because in the latter case, it's easy to confuse input and output, and it's not at all clear that xis being modified.

因为在后一种情况下,很容易混淆输入和输出,并且根本不清楚x正在修改。

In the particular case of round, you probably need only one or two types for TOutanyway, so you could just leave that template argument out:

在 的特殊情况下round,无论如何您可能只需要一两种类型TOut,因此您可以将该模板参数排除在外:

template<typename TIn>
int roundToInt(TIn v) {
    return (int)(v + 0.5);
}

I find roundToInt(x)a little clearer than round<int>(x)because it's clear what the inttype is used for.

我觉得roundToInt(x)更清楚一点,round<int>(x)因为它很清楚int类型的用途。

回答by Konrad Rudolph

the conclusion be to avoid functions with return and more prefer void functions that return via a reference when writing templates

结论是避免带返回的函数,更喜欢在编写模板时通过引用返回的 void 函数

No, why? What do you gain? Only type inference (so less code to write). But you losethe much more logical syntax of assigning a value (and consequently more code to write). So one thing gained, another lost. I don't see the benefit in general.

没有为什么?你有什么收获?仅类型推断(因此编写的代码更少)。但是您失去了分配值的更合乎逻辑的语法(因此需要编写更多代码)。所以一件事得到了,另一件事失去了。我没有看到一般的好处。

It may even helpto have to specify the template type explicitly: consider the case of lexical_cast. Not specifying the return template type would be confusing.

必须明确指定模板类型甚至可能会有所帮助:考虑lexical_cast. 不指定返回模板类型会令人困惑。

回答by wheaties

Let me add to what the others have said by saying you should prefer C++ casting over C-style casting.

让我补充一下其他人所说的,说您应该更喜欢 C++ 类型转换而不是 C 风格转换。

vret = (TOut)(vin + 0.5);

versus

相对

vret = static_cast<TOut>(vin + 0.5);

static cast will always fail if you try to convert unrelated types. This can help with debugging.

如果您尝试转换不相关的类型,静态转换将始终失败。这有助于调试。