Home > Software engineering >  C Sized template deduction
C Sized template deduction

Time:08-30

I want to create a wrapper around with std::array with some extended functionality. The class should be instantiable via an std::initializer_list. I also need a constructor to which I can pass an existing instance of the class plus a "suffix", meaning that the instance need to be of size 1.

#include <stddef.h>
#include <array>
#include <initializer_list>

template<size_t L>
class JsonPointer {
public:
   constexpr JsonPointer(std::array<const char*, L> segments)
        : m_path_segments(std::move(segments))
    {
    }

    constexpr JsonPointer(std::initializer_list<const char*> list) : m_path_segments(std::array<const char*, list.size()>)
    {
    }

    template<size_t S>
    JsonPointer(JsonPointer<S> existing, const char* suffix)  {
    }

private:
    std::array<const char*, L> m_path_segments;
};

int main(){
    constexpr JsonPointer base_ptr {"a", "n"};
    auto ptr = JsonPointer(base_ptr, "test");
}

How can I use the size of std::initializer_list for constexpr initialization? In the "expansion", how can I make the deducation realize that S=L 1?

CodePudding user response:

with C 20 you can achieve this by adding 2 user defined deduction guides:

template<typename... Ts>
JsonPointer(Ts... ts)->JsonPointer<sizeof...(Ts)>;

template<size_t S>
JsonPointer(JsonPointer<S> existing, const char* suffix)->JsonPointer<S   1>;

they allow the compiler to find the correct deduction without naming the full template.


template<size_t L>
class JsonPointer {
public:
    constexpr JsonPointer(std::array<const char*, L> segments)
        : m_path_segments(std::move(segments))
    {
    }

    constexpr JsonPointer(std::initializer_list<const char*> list) : m_path_segments() {
        std::copy(list.begin(), list.end(), this->m_path_segments.begin());
    }

    template<size_t S>
    constexpr JsonPointer(JsonPointer<S> existing, const char* suffix) : m_path_segments() {
        std::copy(existing.m_path_segments.begin(), existing.m_path_segments.end(), 
            this->m_path_segments.begin());
        this->m_path_segments.back() = std::move(suffix);
    }

    template<size_t S>
    friend class JsonPointer;
private:
    std::array<const char*, L> m_path_segments;
};

template<typename... Ts>
JsonPointer(Ts... ts)->JsonPointer<sizeof...(Ts)>;

template<size_t S>
JsonPointer(JsonPointer<S> existing, const char* suffix)->JsonPointer<S   1>;

int main() {
    constexpr JsonPointer base_ptr{ "a", "n" };
    constexpr auto ptr = JsonPointer(base_ptr, "test");
}

the constexpr ptr now holds {"a", "n", "test"}

try it out

  • Related