mardi 26 septembre 2023

Specialize C++11 template based on type traits while allowing fallback for other types

I am currently working on serializing several data structures to JSON.

The existing data structures already provide a text-based output format that I want to use as the default when the functions that convert a specific type to JSON not yet exists.

I currently have the fallback and several specific specializations done. As the JSON-library I use is already able to consume primintives like int, float etc. without any extra work, I want these types have their own (common) specialized template function.

My current main problem is that I'm not able to get to_json(1) to call the function for fundamentals/primitives, but if I specify the type manually (to_json<int>) the correct function is called. Is there any way to fix this? What type does the compiler deduce in the first line?

I am limited to C++11.

The following summarizes my basic setup


#include <iostream>
#include <type_traits>

// Should rely on fallback
struct S {
};

// Has specialization
struct R {
};


// Fallback. Should catch everything not caught by the specializations
template <typename T>
void to_json(const T& x);


// Specialization for R
template<>
void to_json(const R& x)
{
    std::cout << "For R\n";
}

// Does not work
// Specialization for all fundamentals (e.g. int)
template<typename T>
void to_json(const typename std::enable_if<std::is_fundamental<T>::value, T>::type& x)
{
    std::cout << "For fundamentals\n";
}

template <typename T>
void to_json(const T& x)
{
    std::cout << "General\n";
}

int main()
{
    to_json(1);      // General. (WRONG, expected fundamentals)
    to_json<int>(1); // fundamentals (CORRECT)
    to_json(R{});    // R (CORRECT)
    to_json(S{});    // General (CORRECT)

    return 0;
}

Output:

General
For fundamentals
For R
General

Aucun commentaire:

Enregistrer un commentaire