0

I was trying if I could replace my code for 2-, 3- and 4--dimensional vectors into 1 class, so instead of having vec2<T>, vec3<T> and vec4<T>, use vecN<typenameT,unsignedS>.

That seems to work well but the overloaded cout function for printing the vectors gives an undefined reference error. I cannot see what I'm doing differently than the usual:

(minimised) class vectors.hpp:

#include<vector>
#include<iostream>
#include<ranges>

template <typename T, unsigned S>
class vecN {
  template <typename U> friend std::ostream& operator<< ( std::ostream& out, const vecN<U,S>& v);
  template <typename U> friend std::istream& operator>> ( std::istream&  in,       vecN<U,S>& v);
protected:
  std::vector<T> 
  data;
public:
  vecN ( T* xyz ): data ( S ) { std::copy (xyz, xyz+S, data.begin() ); }
};

// non-members of vecN for vecN
template <typename T, unsigned S>
std::ostream& operator<<(std::ostream& out, const vecN<T,S>& v) { 
    out << "( ";
    std::copy(v, std::ostream_iterator<char>(out, ", "));
    out << "\b\b )"; // use two ANSI backspace characters '\b' to overwrite final ", "
    return out; 
}

template <typename T, unsigned S>
std::istream& operator>>(std::istream& in , vecN<T,S> &v) { 
    for ( auto i : std::views::iota(0u, S) )
        in >> v.data[i]; 
    return in;
}

// aliases for 2-, 3- and 4-dimensional vectors
template <typename T>
using vec2 = vecN<T,2>;

template <typename T>
using vec3 = vecN<T,3>;

template <typename T>
using vec4 = vecN<T,4>;

Test file main.cpp:

#include "vectors.hpp"
int main() {  
  float v[2] = { 10, 20 };
  vec2<float> v2_1 ( v );  
  std::cout << "vector v2_1 \n" << v2_1 << "\n";  
  return 0;  
}

When I compile them with:

g++ -std=c++20 -o test main.cpp vectors.hpp 

then I get the error

in function `main':
main.cpp:(.text+0x6a): undefined reference to `std::ostream& operator<< <float>(std::ostream&, vecN<float, 2u> const&)'
collect2: error: ld returned 1 exit status

But the compiled code for this vector type (float values, size 2) should end up in the test binary, shouldn't it? The types and values are determined correctly, but it does not seem to include the code?

alle_meije
  • 2,424
  • 1
  • 19
  • 40
  • 2
    your friend declaration is for a function with a single template parameter but your definition has two template parameters so doesn't match – Alan Birtles Jan 05 '22 at 12:13
  • Ah thanks! I had good hopes it would be easy -- not sure how I came by the idea that I could "re-use" S as the 2nd parameter, while having to use a new one instead of T... – alle_meije Jan 05 '22 at 13:01

0 Answers0