0

I get 'undefined reference to void Output::Print<char[6]>(char const (&) [6])' when I compile into the main program.

But I don't understand because I'm including the file's header. And crucially also including the file in the compilation/linking phase.

The following commands are my sequence:

  • g++ Output.cpp -c
  • g++ main.cpp Output.o

It doesn't even work with g++ main.cpp Output.cpp. But making the object file Output.o doesn't produce any error, so I don't understand....

Here are the files:

Output.hpp:

#ifndef __PRETTY_OUTPUTTER_FOR_CONSOLE_HPP__
#define __PRETTY_OUTPUTTER_FOR_CONSOLE_HPP__

namespace Output{
    template<typename ... Strings>
    void Print(const Strings&... rest);
}

struct Context{
    Context();
    ~Context();
};

#endif

Output.cpp:

#include <iostream>
#include "Output.hpp"

using namespace std;

namespace Output{
    int context = 0;

    template<typename First, typename... Strings>
    void print_(First arg, const Strings&... rest){
        cout << arg;
        print_(rest...);
    }

    template<typename First>
    void print_(First arg){
        cout << arg;
    }

    template<typename ... Strings>
    void Print(const Strings&... rest){
        for (int i = 0; i < context; i++){
            cout << "\t";
        }
        print_(rest...);
        cout << endl;
    }
};

Context::Context(){Output::context++;}
Context::~Context(){Output::context--;}

main.cpp:

#include "Output.hpp"

int main(){
    Context ot; Output::Print("AHAHA");
    return 0;
}

I've tried to reorganize the header file multiple times. I've tried to include the header while compiling. I've tried to put everything into a single struct.

If I simplify things into one main.cpp file, with a simple namespace, everything works. But not in this form and I don't understand why.

--

Found the Solution: Make the variadic function a normal non-object function, and add 'static' to the start like so:

template<typename ... Strings>
static void print(Strings ... args) {
//...
}

That way the c++ compiler only considers the function as a single translation unit function. Until it's included elsewhere and only used in that single translation unit, repeat ad infinitum.

HMM
  • 27
  • 3
  • Please always define template functions in hpp files. Every cpp file is one compilation unit. Compiler needs to know how to instantiate function from template functions, so it needs to see template function implementation. If the implementation of template function is in the cpp file, then compiler won't be able to instatiate it since it is define in a separate compilation unit (other cpp file). So, please avoid implementation in cpp files, always implement them in header files. – Dzemo997 Jul 16 '23 at 08:36
  • @Dzemo997 How do I avoid the 'multiple reference' of the function then? I'd like to use the functions in multiple different files but header guards aren't helping me. – HMM Jul 16 '23 at 08:40
  • 1
    @HMM Template functions are an exception to the usual rules on multiple definitions. But if it really worries you then simply declare them `inline`. – john Jul 16 '23 at 08:57

0 Answers0