问题描述:

I am new to templates. While going through one of the tutorials i found the following statement:

We have following function template:

template<class T1, class T2>

void PrintNumbers(const T1& t1Data, const T2& t2Data)

{}

Which calls the function in this way:

PrintNumbers<double, double>(10, 100);

Which would produce the following template function:

void PrintNumbers<double, double>(const double& t1Data, const T2& t2Data)

{}

But if i try the exact thing in my program it doesnt work and throws a lot of errors:

template<class T1, class T2>

void PrintNumbers<double, double>(const double& t1Data, const T2& t2Data)

{}

int main()

{

PrintNumbers<double, double>(10, 100);

return 0;

}

But instead of the above function template if i use the following then it works:

template<class T1, class T2>

void PrintNumbers(const T1& t1Data, const T2& t2Data)

{}

Is there a problem in the way i am trying to understand this particular concept?

If so, what exactly would void PrintNumbers<double, double>(const double& t1Data, const T2& t2Data) mean and how it can be used(in which scenario)?

网友答案:

So I think this is an issue of understanding the nuances of template syntax.

There are a few things all of which are very different from the compilers point of view:

  • A template
  • A template specialization
  • A template instantiation

All of these things can happen for structs, for functions, for typedefs, etc.

When you write

template<class T1, class T2>
void PrintNumbers(const T1& t1Data, const T2& t2Data)
{}

that declares a template function. After this, you can use the symbol PrintNumbers as a function with two arguments, and it will instantiate the template, creating a corresponding function with two arguments.

If you want only a specific version, you could just not use templates at all

void PrintNumber(const double &, const double &)
{}

That would be okay.

When you write:

void PrintNumbers<double, double>(const double& t1Data, const T2& t2Data)
{}

this really doesn't mean anything and will be rejected by the compiler. When you put template parameters right after a declarator like that, it is expected to be a template specialization. However,

  • for that you must use the keyword template, even if with empty parameter list like template<> void PrintNumbers<double, double>(const double& t1Data, const T2& t2Data) {}

  • there must have been a PRIOR declaration of a template. You can only make a specialization of a template that already exists, the compiler won't just introduce a template for you. I can't tell you why, that's just how it works.

Usually, the way you should use templates is

  • Declare the "full" template first, using template< foo, bar, baz > my_function(A a, B b, ...) {}
  • Optionally, add some partial specializations, being careful not to make ambiguous partial specializations: template<foo, bar> my_function<foo, bar, bar::baz_type>(A a, B b, ...) {}
  • Now instantiate the template as desired.
网友答案:

Yep I think you are not understanding templates the right way. So when you have a templated function you need to have the definition like so

template <typename T1, typename T2>
void PrintNumbers(const T1& t1Data, const T2& t2Data) {}

and call it like so

PrintNumbers(100.0, 100.0)

and that will resolve the above template to call a function that looks like so

void PrintNumbers(const double& t1Data, const double& t2Data);

What you are trying in the first case would be called explicit template specialization. And you would do it like so

template <typename T1, typename T2>
void PrintNumbers(const T1& t1Data, const T2& t2Data) {}

template <>
void PrintNumbers<double, double> (const double& t1Data, const double& t2Data) {/*Something else here */}

And then when you make function call (1) below that will go to the specialized function, and (2) and (3) will go to the 1st unspecialized one.

PrintNumbers(10.0, 10.0);     // (1)
PrintNumbers("some", "word"); // (2)
PrintNumbers(std::vector<int>(), std::vector<int>()); // (3)

There is also mechanisms in C++ called partial template specialization and non-type templates. I could go into the details of that but that would be enough to fill out a big blog post and then some. You should google them for more details. They are very useful and smart C++ programmers use them to make compile time deductions that are not possible in other languages.

相关阅读:
Top