Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - template instantiation with reference type

Tags:

c++

templates

I've heard a little bit about reference-to-reference problem and this resolution. I'm not very good with C++ Committee terminology, but I understand the "Moved to DR" annotation in the link means that this is the current interpretation that standard-conforming compilers should adhere to.

I have this sample code that I can't understand:

template <typename T>
struct C {
  void f(T&) { }
  void f(const T&) { }
};

int main() {
  C<int> x;        // OK
  C<int&> y;       // compile error: f cannot be overloaded
  C<const int&> z; // compile error: f cannot be overloaded
}

I understand the error in C<const int&> case: using rules from DR #106 we get two methods with the same signature f(const int&). What I don't get is the C<int&> case: shouldn't it generate exactly the same code as C<int> (at least according to Stroustrup's resolution)?

like image 298
jhh Avatar asked Nov 10 '10 12:11

jhh


People also ask

How do I force a template instantiation?

To instantiate a template function explicitly, follow the template keyword by a declaration (not definition) for the function, with the function identifier followed by the template arguments. template float twice<float>(float original); Template arguments may be omitted when the compiler can infer them.

Is it necessary to instantiate a template?

In order for any code to appear, a template must be instantiated: the template arguments must be provided so that the compiler can generate an actual class (or function, from a function template).

How do you call a function in a template?

A function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.

What is implicit instantiation?

Implicit instantiation means that the compiler automatically generates the concrete function or class for the provided template arguments. In general, the compiler also deduces the template arguments from the function's arguments. In C++17, the compiler can also deduce the template arguments for class templates.


2 Answers

DR only means "Defect Report", and to my knowledge, the described resolution hasn't made it (yet) to the standard. For this reason, I believe a strictly conforming C++03 implementation should not compile this code because of it is forming a reference to a reference.

[Edit] Just found a nice answer on this issue.

like image 107
icecrime Avatar answered Sep 21 '22 16:09

icecrime


Interestingly, when I compile your code (Visual C++ 10 Express) I get errors, but also when I try this simpler case:

int main(int argc, char* argv[]) 
{
  C<int> x;        // OK
  C<const int> x1; // error C2535: 'void C<T>::f(T &)' : member function 
                   // already defined or declared
  return 0;
}

Seems like the ref-to-ref collapsing defined in the DR you mentioned means that const ref becomes a simple non-const ref within the template. My problem with this is that I don't understand why the second f is not just ignored.

If I change C so that the second f is const-qualified, this now compiles:

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

The implication seems to be that when C is instantiated with const anything (ref or not), the two C::f overloads are simply identical, and result in compile-time duplicate detection.

Perhaps somebody smarter than me can decipher the chain more definitively here.

EDIT: On reflection, it's not surprising here that T = const int& results in the f overloads being identically instantiated as

void f(const int&) {}

That's what the compiler is telling me:

#include "stdafx.h"

template <typename T>
struct C {
  void f(T&) { }
  void f(const T&) { }
};

int main() {
  C<const int&> z; // compile error: f cannot be overloaded
  return 0;
}

gives this error:

1>test.cpp(6): error C2535: 'void C<T>::f(T)' : member function already 
    defined or declared
1>          with
1>          [
1>              T=const int &
1>          ]
1>          test.cpp(5) : see declaration of 'C<T>::f'
1>          with
1>          [
1>              T=const int &
1>          ]
1>          test.cpp(10) : see reference to class template instantiation 
                'C<T>' being compiled
1>          with
1>          [
1>              T=const int &
1>          ]

I'm not even convinced this has anything to do with the DR.

like image 44
Steve Townsend Avatar answered Sep 20 '22 16:09

Steve Townsend