1

I'm trying to write a function that implements a general behavior for all types that are not enums, a general behavior for all types that are enums, and then being able to specialize a specific behavior for some types by fully specializing the function. Here is my code so far:

// Func.h

#include <cstdio>
#include <type_traits>

template <typename T, std::enable_if_t<!std::is_enum<T>{}>* = nullptr >
void Func()
{
    printf("General case\n");
}

template <typename T, std::enable_if_t<std::is_enum<T>{}>* = nullptr >
void Func()
{
    printf("enum\n");
}

template <>
void Func<bool>()
{
  printf("bool\n");
}


// main.cpp
#include <Func.h>

enum Enum
{
    A,
    B
};

int main()
{
  Func<float>();
  Func<Enum>();
  Func<bool>();
}

It does not compile and I don't really know how to get that right. If i let the specialized prototype as in the code above, I get this linking error:

error LNK2005: "void __cdecl Func<bool,0>(void)" (??$Func@_N$0A@@@YAXXZ) already defined in main.obj

and if I make the specialized prototype template<> void Func<bool, nullptr>(), I get this compilation error:

error C2912: explicit specialization 'void Func<bool,nullptr>(void)' is not a specialization of a function template

These tests are done using Visual Studio 2015 compiler with c++14 standard

I don't know where to go from here, any help would be greatly appreciated

Grouflon
  • 57
  • 1
  • 6

1 Answers1

2

You get a linking error because Func<bool>() is defined in a header file that is included into multiple compilation units. Solution is simple: put inline before void Func<bool>():

template<>
inline void Func<bool>()
{
    // ...
}

Function templates are implicitly inline, but functions and explicit template specializations are not. If they are defined in a header file, they should be marked as inline.

Evg
  • 25,259
  • 5
  • 41
  • 83
  • Ho right, I noticed that it also work if you move the definition of the function in the corresponding cpp file. What I don't get though is why fully specialized template functions get multiple declaration when simply declared in the header where regular function do not. – Grouflon Apr 26 '20 at 11:47
  • 1
    Each time you include "Func.h", a compiler generates code for `Func()`. You get as many copies of it as the number of compilation units that include this header. Regular functions follow exactly the same rule. – Evg Apr 26 '20 at 11:49