简体   繁体   English

模板函数中引用类型的推导

[英]Deduction of reference types in template functions

Do I have to explicitly instantiate a function template's type when it comes to reference type deduction. 在引用类型推导时,是否必须显式实例化函数模板的类型。 If that is the case, where is the ambiguity? 如果是这样的话,歧义在哪里? Let's compare following 2 code snippets: 让我们比较以下2个代码段:

1st: link for the code 1st: 代码的链接

template <typename T> 
void foo(T& var, void(*func)(T&)) // T must be instantiated with int and it does .
{
 ++var;
} 
void ret(int & var){}
int main()
{int k =7; 
foo(k, &ret);
cout<<k;//prints 8
}

Now let's remove &'s in foo()'s decleration and we have an error. 现在让我们删除foo()中的&f',我们有一个错误。

2nd: link for the code 第二: 代码的链接

template <typename T> 
void foo(T var, void(*func)(T)) // T must be instantiated with int& but it doesn't.
{
 ++var;
} 

void ret(int & var){}

int main()
{int k =7; 

foo(k, &ret); //error: no matching function for call to 'foo(int&, void (*)(int&))'
cout<<k;
}

However, If I call foo by explicitly instantiating with <int&> " foo<int&>(k,&ret); ", the code gives the same output as the former one. 但是,如果我通过使用<int&>foo<int&>(k,&ret); ”显式实例化来调用foo,则代码将提供与前者相同的输出。 What is the reason of this error? 这个错误的原因是什么? Where is the ambiguity? 歧义在哪里?

Thanks. 谢谢。

As highlighted in Fionn's answer , the problem is that the compiler deduces two distinct types for T , int and int& . 正如Fionn的回答中强调的那样,问题是编译器为Tintint&推导出两种不同的类型。 18.8.2.4/2 has the following: 18.8.2.4/2有以下内容:

In some cases, the deduction is done using a single set of types P and A, in other cases, there will be a set of corresponding types P and A. Type deduction is done independently for each P/A pair, and the deduced template argument values are then combined. 在某些情况下,使用单一类型P和A进行推导,在其他情况下,将有一组对应的类型P和A.类型推导是针对每个P / A对独立完成的,并且推导出的模板然后组合参数值。 If type deduction cannot be done for any P/A pair, or if for any pair the deduction leads to more than one possible set of deduced values , or if different pairs yield different deduced values, or if any template argument remains neither deduced nor explicitly specified, template argument deduction fails. 如果不能对任何P / A对进行类型推导,或者对于任何对,则推导导致多个可能的推导值集 ,或者如果不同的对产生不同的推导值,或者如果任何模板参数既不推断也不明确指定的模板参数推断失败。

The highlighted text I believe covers your example. 我认为突出显示的文字涵盖了您的示例。 You didn't ask, but one option you potentially have is to use two template parameters in your example. 您没有问,但您可能有一个选项是在示例中使用两个模板参数。 Both of these cases can be deduced, so you could then use some other template trickery possibly via enable if to create a new type which represents the version you want, ie. 这两种情况都可以推断出来,因此您可以使用其他一些模板技巧,可以通过启用if if创建一个代表您想要的版本的新类型,即。 with reference or without. 参考或不参考。

Second version of the answer, just misinterpreted the question: 答案的第二个版本,只是误解了这个问题:

The problem with the second version is that the compiler just can't know if you want to pass by reference or pass by value. 第二个版本的问题是编译器无法知道您是想通过引用传递还是传递值。

The calling syntax for both is exactly the same, but you obviously want to pass by reference - else the increment doesn't make any sense. 两者的调用语法完全相同,但您显然希望通过引用传递 - 否则增量没有任何意义。

Here an example to show there is no difference how you call an function with a pass by reference and one with a pass by value argument: 这里有一个例子来说明如何通过引用传递函数和使用pass by value参数调用函数没有区别:

void Incr1(int &value) { value++; }
void Incr2(int value) { value++ } //Completely useless but for demonstration

//Now the calling of both functions
int x = 1;
Incr1(x);
Incr2(x);

If you use a pointer instead of a reference, the compiler knows what to do because you explicitly tell it that you pass a pointer to int. 如果使用指针而不是引用,编译器会知道该怎么做,因为您明确告诉它您将指针传递给int。

#include <iostream>

template <typename T> 
void foo(T var, void(*func)(T))
{
    ++(*var);
} 

void ret(int *var){}

int main()
{
    int k =7; 

    foo(&k, &ret); 
    std::cout<<k;
}

This will make it compile but there is not much sense in it: 这将使它编译,但它没有多大意义:

The error is that your function still takes a T& and not a T. 错误是你的功能仍然需要T&而不是T.

So you just need this little modification: 所以你只需要这个小修改:

template <typename T> 
void foo(T var, void(*func)(T&))
{
 ++var;
} 

void ret(int & var){}

int main()
{
    int k =7; 

    foo(k, &ret);
    std::cout<<k;
}

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

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