Grouflon
Grouflon

Reputation: 57

full specialization of template functions with std::if_enabled_t parameter

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

Upvotes: 1

Views: 57

Answers (1)

Evg
Evg

Reputation: 26282

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.

Upvotes: 2

Related Questions