简体   繁体   English

在哪些情况下需要特别指定模板的参数“types”?

[英]In which cases one needs to specify the template's argument `types` specifically?

// Function declaration.
template <typename T1, 
          typename T2, 
          typename RT> RT max (T1 a, T2 b);

// Function call.
max <int,double,double> (4,4.2)

// Function call.
max <int> (4,4.2)

One case may be when you need to specify the return type.一种情况可能是您需要指定返回类型。

Is there any other situation which requires the argument types to be specified manually?是否有任何其他情况需要手动指定参数类型?

(1) When there is no argument to the function and still it's a template type, then you may have to specify the arguments explicitly (1)当函数没有参数并且仍然是template类型时,您可能必须显式指定参数

template<typename T>
void foo ()
{}

Usage:用法:

foo<int>();
foo<A>();

(2) You want to distinguish between value and reference . (2)你要区分 value 和 reference

template<typename T>
void foo(T obj)
{}

Usage:用法:

int i = 2;
foo(i); // pass by value
foo<int&>(i); // pass by reference

(3) Need another type to be deduced instead of the natural type. (3)需要推导另一种类型而不是自然类型。

template<typename T>
void foo(T& obj)
{}

Usage:用法:

foo<double>(d);  // otherwise it would have been foo<int>
foo<Base&>(o); // otherwise it would have been foo<Derived&>

(4) Two different argument types are provided for a single template parameter (4)为单个模板形参提供两种不同的实参类型

template<typename T>
void foo(T obj1, T obj2)
{}

Usage:用法:

foo<double>(d,i);  // Deduction finds both double and int for T

If the function template parameter appears in the function parameter list, then you don't need to specify the template parameters.如果函数模板参数出现在函数参数列表中,则不需要指定模板参数。 For example,例如,

template<typename T>
void f(const T &t) {}

Here T is a template parameter, and it appears in the function parameter list, ie const T &t .这里T是一个模板参数,它出现在函数参数列表中,即const T &t So you don't need to specify the template parameter when calling this function:所以调用这个函数时不需要指定模板参数:

f(10); //ok

Since the type of 10 is int , so the compiler can deduce the template parameter T from it, and T becomes int .由于10类型int ,所以编译器可以从中推导出模板参数 T ,而T变为int

Note that since the type deduction is done from using the information of the function arguments, its called template argument deduction .请注意,由于类型推导是使用函数参数的信息完成的,因此称为模板参数推导 Now read on.现在继续阅读。

If the template parameter doesn't appear in the function parameter list, then you have to provide the template parameter.如果模板参数没有出现在函数参数列表中,那么您必须提供模板参数。 Example:例子:

template<typename T>
void g(const int &i) {}

Notice g() is different from f() .注意g()f()不同。 Now T doesn't appear in the function parameter list.现在T没有出现在函数参数列表中。 So:所以:

g(10); //error
g<double>(10); //ok

Note that if a function template templatizes on the return type as well, and the return type is different from the types appearing the function parameter list, then you've to provide the return type:请注意,如果函数模板也对返回类型进行模板化,并且返回类型与函数参数列表中出现的类型不同,那么您必须提供返回类型:

template<typename T>
T h(const T &t) {}

Since return type T is same as the function parameter, type deduction is possible from function argument:由于返回类型T与函数参数相同,因此可以从函数参数中进行类型推导:

h(10); //ok - too obvious now

But if you've this:但如果你有这个:

template<typename R, typename T>
R m(const T &t) {}

Then,然后,

m(10);  //error - only T can be deduced, not R
m<int>(10);  //ok

Note that even though the function template m has templatized on two types : R and T , we've provided only ONE type when calling it.请注意,即使函数模板m已经模板化了两种类型: RT ,我们在调用它时只提供了一种类型。 That is, we've written m<int>(10) as opposed to m<int,int>(10) .也就是说,我们编写了m<int>(10)而不是m<int,int>(10) There is no harm in writing the later, but its okay, if you don't.写后者没有坏处,但如果你不这样做,也可以。 But sometimes you've to specif both, even if one type T can be deduced.但有时您必须同时指定两者,即使可以推断出一种类型T It is when the order of type parameters is different as shown below:类型参数的顺序不同时,如下所示:

template<typename T, typename R> //note the order : its swapped now!
R n(const T &t) {}

Now, you've to provide both types:现在,您必须提供两种类型:

n(10); //error - R cannot be deduced!
n<int>(10); //error - R still cannot be deduced, since its the second argument!
n<int,int>(10); //ok

The new thing here is : the order of type parameters is also important .这里的新东西是:类型参数的顺序也很重要

Anyway, this covers only the elementary concept.无论如何,这仅涵盖基本概念。 Now I would suggest you to read some good book on templates, to learn all the advanced things regarding type deduction.现在我建议你阅读一些关于模板的好书,学习关于类型推导的所有高级知识。

In general, you need to explicitly specify the types when the compiler can't figure it out on its own.通常,当编译器无法自行判断时,您需要显式指定类型。 As you mentioned, this often happens when the return type is templatized, since the return type cannot be inferred from the function call.正如您所提到的,这通常在返回类型被模板化时发生,因为无法从函数调用中推断出返回类型。

Template classes have the same problem -- instantiating a std::vector offers no way for the compiler to determine what type your vector is storing, so you need to specify std::vector<int> and so forth.模板类有同样的问题——实例化std::vector无法让编译器确定你的向量存储的类型,所以你需要指定std::vector<int>等等。

The type resolution is only performed in the case of function arguments, so it may be easier to view that as the special case;类型解析仅在函数参数的情况下执行,因此将其视为特殊情况可能更容易; ordinarily, the compiler is unable to guess what type(s) to use.通常,编译器无法猜测要使用的类型。

The simple answer is that you need to provide the types when the compiler cannot deduce the types by itself, or when you want the template to be instantiated with a particular type that is different from what the compiler will deduce.简单的答案是,当编译器无法自行推断类型时,或者当您希望使用不同于编译器推断的特定类型来实例化模板时,您需要提供类型。

There are different circumstances when the compiler cannot deduce a type.当编译器无法推断出类型时,存在不同的情况。 Because type deduction is only applied to the arguments (as is the case with overload resolution) if the return type does not appear as an argument that is deducible, then you will have to specify it.因为类型推导仅适用于参数(如重载决议的情况),如果返回类型不作为可推导的参数出现,那么您必须指定它。 But there are other circumstances when type deduction will not work:但是还有其他情况下类型推导不起作用:

template <typename R> R f(); // Return type is never deduced by itself
template <typename T>
T min( T const & lhs, T const & rhs );
min( 1, 2 );                 // Return type is deducible from arguments
min( 1.0, 2 );               // T is not deducible (no perfect match)
min<double>( 1.0, 2 );       // Now it is ok: forced to be double
min<double>( 1, 2 );         // Compiler will deduce int, but we want double

template <typename T>
void print_ptr( T* p );
print_ptr<void>( 0 );        // 0 is a valid T* for any T, select manually one

template <typename T>
T min( T lhs, T rhs );
int a = 5, b = 7;
min<int&>(a,b)++;            // Type deduction will drop & by default and call
                             // min<int>(a,b), force the type to be a reference

template <typename C>
typename C::value_type
min_value( typename C::const_iterator begin, typename C::const_iterator end );
std::vector<int> v;
min_value<std::vector<int> >( v.begin(), v.end() ); 
                                 // Argument type is not deducible, there are 
                                 // potentially infinite C that match the constraints
                                 // and the compiler would be forced to instantiate
                                 // all

There are probably more reasons for an argument type cannot be deduced, you can take a look at §14.8.2.1 in the standard for the specifics of deduction of arguments from a function call.无法推断出参数类型可能还有更多原因,您可以查看标准中的第 14.8.2.1 节,了解从函数调用中推断出参数的细节。

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

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