3
votes

I want to provide a function in my library:

namespace Foo {
template<typename G>
typename std::enable_if<std::is_fundamental<G>::value, std::vector<uint8_t>>::type toBytes(const G &g) {
//something here
}
}

However I want to provide basic implementation only for basic types. If an user wants to add a specialization I thought it was enough to write in the user code:

namespace Foo {
template<>
std::vector<uint8_t> toBytes<struct A>(const struct A &g) {
//something here
}
}

However it doesn't compile, Gcc provides this error:

std::vector Foo::toBytes(const A&)’ does not match any template declaration

Am I missing anything?

1
Common wisdom is to overload, not specialize in such cases.StoryTeller - Unslander Monica

1 Answers

1
votes

I would make use of the C++20 feature Concept.Concepts naturally also support template specialization:

#include <iostream>

namespace detail {
    template<typename T, typename U >
    concept SameHelper = std::is_same_v<T, U>;
}

template<typename T, typename U >
concept same_as = detail::SameHelper<T, U> && detail::SameHelper<U, T>;

template<typename T>
concept fundamental = same_as<T, bool> || same_as<T, char>;

template<typename T>
void toBytes(T) {std::cout << "I am not fundamental" << std::endl;}  

template<fundamental T>
void toBytes(T){std::cout << "I am fundamental" << std::endl;}


int main() {
    toBytes(true);
    toBytes('c');
    toBytes(1);
}

You can run the code online to see the following output:

I am fundamental
I am fundamental
I am not fundamental