c++gccfstreammsys2wchar-t

Why do c++ standard library template class functions say undefined reference while linking if they are defined in a header


When using <fstream> with g++ -D_GLIBCXX_HAVE__WFOPEN=1 -D_GLIBCXX_USE_WCHAR_T=1 (msys2 gcc 13.3.0) it throws an error

/usr/lib/gcc/x86_64-pc-msys/13.3.0/../../../../x86_64-pc-msys/bin/ld: /tmp/cceEWaVo.o:x.cpp:(.text+0x50): undefined reference to `std::basic_ifstream<char, std::char_traits<char> >::open(wchar_t const*, std::_Ios_Openmode)'

code:

#include <fstream>
int main() {


        std::ifstream f("x.cpp"); // works
        f.close();
        f.open(L"x.cpp"); // doesn't link

        return 0;
}

even thou they are defined in <bits/fstream.tcc> witch is included at the end of <fstream>

I was expecting the code to compile normally since ifstream is a template class and is defined in a header. I checked if the code in <bits/fstream.tcc> that defines the open(wchar_t const* __s, std::ios_base::openmode __mode) is detected by the compiler by editing the header file and putting a #error block right above the function and the compiler found if (which means that all the ifdefs where passed)

Could someone please explain why header-defined template class functions need to also somehow exist in libstdc++

I am aware that the mingw-w64 gcc compiler works with fstream open(wchar_t const* __s, std::ios_base::openmode __mode) but I specificly need the msys version


Solution

  • The basic_ifstream template is declared extern template class basic_ifstream<char>. Thus, the template is not instantiated in a user code, it's instantiated in libstdc++. Since the latter is compiled w/o the implementation defined macros mentioned in the question, the user code gets the undefined reference to std::basic_ifstream<char, std::char_traits<char>>::open(wchar_t const*, std::_Ios_Openmode)'.