I'm getting linking error while compiling this program. This is not the actual code though... but this mimics what I'm experiencing issues with. Also this code produces the same error.
I've defined a class ArrayEnc
which is a template class with non-type template parameter. The interface of the class is defined in a header file and the implementation of all the methods (also ctors) is defined in a separate translation unit.
I'm getting a linking error if I try to construct an object of ArrayEnc
class within another class User
, which intends to use it.
The errors disappear when I move the implementation code (as it is) from the separation translation unit to the header file.
What could be off here?
Contents of Header File: ArrEnc.h
#pragma once
#include <array>
#include <iostream>
#include <string>
template <size_t size>
class ArrayEnc
{
public:
ArrayEnc() noexcept;
ArrayEnc(const std::array<int, size>& arr, const std::string& usage = "DefaultUsage");
ArrayEnc(const int arr[size], const std::string& usage);
template <size_t sz>
friend std::ostream& operator<<(std::ostream& os, const ArrayEnc<sz>& ae);
private:
std::array<int, size> m_Arr;
std::string usageHint;
};
template<size_t size>
ArrayEnc<size>
::ArrayEnc() noexcept
:m_Arr()
{}
template <size_t size>
ArrayEnc<size>
::ArrayEnc(const std::array<int, size>& arr, const std::string& usage)
:m_Arr(std::move(arr)),
usageHint(usage)
{}
template <size_t size>
ArrayEnc<size>
::ArrayEnc(const int arr[size], const std::string& usage)
:m_Arr(arr),
usageHint(usage)
{}
template<size_t size>
std::ostream& operator<<(std::ostream& os, const ArrayEnc<size>& ae)
{
os << "Usage Hint: "<<ae.usageHint<<std::endl;
for(const auto& elem : ae.m_Arr)
{
os << elem<<", ";
}
return os;
}
Contents of implementation file: ArrayEnc.cpp
#include "ArrayEnc.h"
template<size_t size>
ArrayEnc<size>
::ArrayEnc() noexcept
:m_Arr()
{}
template <size_t size>
ArrayEnc<size>
::ArrayEnc(const std::array<int, size>& arr, const std::string& usage)
:m_Arr(std::move(arr)),
usageHint(usage)
{}
template <size_t size>
ArrayEnc<size>
::ArrayEnc(const int arr[size], const std::string& usage)
:m_Arr(arr),
usageHint(usage)
{}
template<size_t size>
std::ostream& operator<<(std::ostream& os, const ArrayEnc<size>& ae)
{
os << "Usage Hint: "<<ae.usageHint<<std::endl;
for(const auto& elem : ae.m_Arr)
{
os << elem<<", ";
}
return os;
}
Now this is how I'm testing this...
Test.cpp
#include "ArrayEnc.h"
class User
{
public:
User()
:array(
{
0, 1, 2,
2, 3, 0
}
)
{}
void display() const noexcept
{
std::cout<<array<<std::endl;
}
private:
ArrayEnc<6> array;
};
int main()
{
User u;
u.display();
}
I'm compiling using: g++ -lstdc++ -std=c++17 ArrayEnc.cpp Test.cpp -o Test
I tried moving the code in the header file and skipped compiling of the translation unit, then it worked as expected. Moving the implementation code in a translation unit, and then compiling with it is causing my troubles of linking error. I get the following message:-
C:\Users\UserName\AppData\Local\Temp\cchYeN1s.o: In function `User::User()':
C:\Users\UserName\Dev\C++/./Test.cpp:12: undefined reference to `ArrayEnc<6ull>::ArrayEnc(std::array<int, 6ull> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
C:\Users\UserName\AppData\Local\Temp\cchYeN1s.o: In function `User::display() const':
C:\Users\UserName\Dev\C++/./Test.cpp:17: undefined reference to `std::ostream& operator<< <6ull>(std::ostream&, ArrayEnc<6ull> const&)'
collect2.exe: error: ld returned 1 exit status