MAChitgarha
MAChitgarha

Reputation: 4298

Explicitly specialize templated constructor with zero arguments

Suppose the following class:

class JsonDocument
{
public:
    using RootType = size_t;
    constexpr static RootType ObjectRoot = 1;
    constexpr static RootType ArrayRoot = 2;

    template<
        RootType T = ObjectRoot,
        std::enable_if<T == ObjectRoot || T == ArrayRoot>
    >
    JsonDocument();

    JsonDocument(const std::string &json_str);
};

I want to specialize JsonDocument constructor for both ObjectRoot and ArrayRoot. The problem is, as there are no arguments, T couldn't be inferred. Explicitly specializing it doesn't work, neither this way:

class JsonDocument
{
    // ...

    // Doesn't work
    template<> JsonDocument<ObjectRoot>();
    template<> JsonDocument<ArrayRoot>();
}

Nor this:

template<> JsonDocument::JsonDocument<ObjectRoot>()
{
}

template<> JsonDocument::JsonDocument<ArrayRoot>()
{
}

So is it impossible at all? Is there any way to do it?

P.S.: This question is different; as deduction can be made.

Upvotes: 0

Views: 41

Answers (1)

Pepijn Kramer
Pepijn Kramer

Reputation: 13110

Make the whole class a template. I think this makes sense because you are going to select which root to use at compile time anyway. (C++17 example)

#include <type_traits>

struct ObjectRoot
{};

struct ArrayRoot
{};

// helper constexpr for readability (in C++20 consider a concept)
template<typename root_t>
constexpr bool is_valid_json_root = std::is_same_v<root_t, ObjectRoot> || std::is_same_v<root_t, ArrayRoot>;

template<typename root_t,typename enable_t = void>
class JsonDocument;

template<typename root_t>
class JsonDocument<root_t,std::enable_if_t<is_valid_json_root<root_t>>>
{
public:
    // no need for compile time constants. 
    // you make the selection for your root_t at compile time anyway
    //using RootType = size_t;
    //constexpr static RootType ObjectRoot = 1;
    //constexpr static RootType ArrayRoot = 2;

    JsonDocument() {}


};

int main()
{
    JsonDocument<ObjectRoot> doc_from_root;
    JsonDocument<ArrayRoot> doc_from_array;
}

Upvotes: 0

Related Questions