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"}