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

发布于 2024-09-01 09:17:27 字数 933 浏览 9 评论 0 原文

如果我有一个带有 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> 

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

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>

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

但是,如果我使用 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>

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

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:

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.

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

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 void functions 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

爱你是孤单的心事 2024-09-08 09:17:27

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

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

double x = round<double>(y);

而不是这样:

double x;
round(x, y);

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

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

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

我发现 roundToInt( x) 比 round(x) 更清晰一点,因为 int 类型的用途很清楚。

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 x is being modified.

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

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 int type is used for.

怎言笑 2024-09-08 09:17:27

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

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

必须显式指定模板类型甚至可能会有所帮助:考虑 lexical_cast 的情况。不指定返回模板类型会令人困惑。

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

No, why? What do you gain? Only type inference (so less code to write). But you lose the 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 help to have to specify the template type explicitly: consider the case of lexical_cast. Not specifying the return template type would be confusing.

北音执念 2024-09-08 09:17:27

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

vret = (TOut)(vin + 0.5);

相比

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

如果您尝试转换不相关的类型,与静态转换 总是会失败。这可以帮助调试。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文