0
#include <iostream>
using std::cout;


template<typename T>
class A{
  public:
  template<typename U>
  void f(U const&)  & ;
  template<typename U>
  void f(U const&) && ;
};


  template<typename T>
  template<typename U>
   void A<T>::f(U const& x)  & { std::cout << "lvalue object\n" ; }
  template<typename T>
  template<typename U>
   void A<T>::f(U const& x) && { std::cout << "rvalue object\n" ; }

// template class A<int> ;
// template void A<int>::f<int>(int const&) & ;
// template void A<float>::f<int>(int const&) &&;


int main(){

  A<int>   a    ;
           a.f<int>(2); // lvalue
  A<float>().f<int>(1); // rvalue
}

The code runs, other than if I try to break it into separate-compilation (*.hh, *.cc, *.ie and main). The (commented-out) statements will issue a compiler ICE.

I don't see anything wrong with the instantiation syntax. Could someone help me out on this ...

T.C.
  • 133,968
  • 17
  • 288
  • 421

2 Answers2

0

The code runs, other than if I try to break it into separate-compilation (*.hh, *.cc, *.ie and main).

With templates, you can't separate the header and implementation. It's got to be all in one place. You would have to do something like this (keep in mind, I haven't tested this):

A.hpp:

#include <iostream>
using std::cout;


template<typename T>
class A{
  public:
  template<typename U>
  void f(U const&)  & ;
  template<typename U>
  void f(U const&) && ;
};

  // Consider just throwing this in the class definition itself
  template<typename T>
  template<typename U>
   void A<T>::f(U const& x)  & { std::cout << "lvalue object\n" ; }
  template<typename T>
  template<typename U>
   void A<T>::f(U const& x) && { std::cout << "rvalue object\n" ; }

main.cpp

#include "A.hpp"

int main(){
  A<int>   a;
           a.f<int>(2); // lvalue
  A<float>().f<int>(1); // rvalue
}
AlexB
  • 78
  • 4
  • I know it works in one-piece. It fails in separate-compilation. I separate-compile templates like this: *.hh, *.cc (with an include to template instantiations, that I call *.ie). Then all compiles, at the end instantiates and goes into a library. Instantiates how much/many I care to instantiate, of course. Those go in the library (not more). – Tatyana Fedorovna Jul 08 '16 at 19:43
  • You'll have to break it down exactly how you're separating them (show us what's in each file). If you're separating the implementation of the template from the template class definition, it's not going to work. – AlexB Jul 08 '16 at 19:49
0
// ---------------- *.hh ------------

#include <iostream>
using std::cout;


#include <iostream>

template<typename T>
class A{
  public:
  void f()  & ;
  void f() && ;
  void g()  ;
  void g(int)  ;
};


// ---------- *.cc -- you compile this (no linking) just lib code ------
#include "e.hh"

  template<typename T>
   void A<T>::f()  & { std::cout << "lvalue object\n" ; }
  template<typename T>
   void A<T>::f() && { std::cout << "rvalue object\n" ; }

  template<typename T>
   void A<T>::g()   { std::cout << "lvalue object\n" ; }
  template<typename T>
   void A<T>::g(int x)  { std::cout << "rvalue object\n" ; }

extern template class A<int> ;
//extern template class A<float> ;
//template void  A<int>::f(float const&)  & ;
//template void  A<int>::f<int>() && ;

template  void A<int>::f() &;
//template void  A<float>::f() && ;


template  void A<int>::g() ;      // see ! ... these work !
template  void A<int>::g(int) ;   // ... but not the ref-qual ones

// ---------------------- *.cc (main) --------------
// here you compile + link the previous one
#include <iostream>
#include "e.hh"
using std::cout;


int main(){

  A<int>   a    ;
           a.f(); // lvalue
//  A<float>().f(); // rvalue
           a.g(); // lvalue
           a.g(3); // lvalue
}
  • note - clang 3.8/C++11, 14, 17/ works ... it is gcc that doesn't - bugzilla seems slow reacting too ! ... I'd switch to Clang, but LLVM is slow. – Tatyana Fedorovna Jul 08 '16 at 20:48