Implicit construction of std :: pair in the construction of variation templates

I have a key value map constexprthat roughly has this definition:

// map with `pos` remaining entries
template<typename K, typename V, size_t pos>
class Map {
public:
    template<class Head, class... Tail>
    constexpr Map(Head head, Tail... tail)
        :
        value{head},
        tail{tail...} {}

    Element<K, V> value;
    const Map<K, V, pos - 1> tail;

    // members etc
};

// map end element.
template<typename K, typename V>
class Map<K, V, 0> {
public:
    constexpr Map() {}

    // end element specifics.
};

To initialize the key value map at compile time, I have a utility function that forwards elements:

template<typename K, typename V, typename... Entries>
constexpr Map<K, V, sizeof...(Entries)> create_const_map(Entries&&... entry) {
    return Map<K, V, sizeof...(entry)>(Entry<K, V>{std::forward<Entries>(entry)}...);
}

Element defined as:

template<class K, class V>
class Entry {
public:
    constexpr Entry(const K &key, const V &value)
        :
        key{key},
        value{value} {}

    constexpr Entry(std::pair<K, V> pair)
        :
        key{pair.first},
        value{pair.second} {}

    const K key;
    const V value;
};

To create a map, I can successfully use std::make_pair:

constexpr auto cmap = create_const_map<int, int>(
    std::make_pair(0, 0),
    std::make_pair(13, 37),
    std::make_pair(42, 9001)
);

Now I want to eliminate the calls std::make_pairand use curly braces instead:

constexpr auto cmap = create_const_map<int, int>(
    {0, 0},
    {13, 37},
    {42, 9001}
);

But this leads to compilation failure, since {}it is not output as a construction for pairs:

/home/jj/devel/openage/libopenage/datastructure/tests.cpp:191:24: error: no matching function for call to 'create_const_map'
        constexpr auto cmap = create_const_map<int, int>(
                              ^~~~~~~~~~~~~~~~~~~~~~~~~~
/home/jj/devel/openage/libopenage/datastructure/constexpr_map.h:286:46: note: candidate function not viable: requires 0 arguments, but 3 were provided
constexpr Map<K, V, sizeof...(Entries)> create_const_map(Entries&&... entry) {
                                        ^

What can I do to {a, b}be able to use instead std::make_pair(a, b)?

+4
2

, , . Entries. , , , . cppreference, "":

-init- , . decltype({1,2}) . , , , -init-list, , template<class T> void f(T);, f({1,2,3}) .

gcc ( cpp.sh) , Entries = {}:

63: 1: : 'constexpr Map create_const_map ( &...) [ K = int; V = int; = {}] '

, , std::make_pair.

+2

, , @Rostislav, , .

, . (operator()) create_map - . Overload. ++ , , , , , , .

template<typename D, int N, typename ...E>
struct OverloadImpl;

template<typename D, int N, typename E, typename ...Es>
struct OverloadImpl<D, N, E, Es...> : OverloadImpl<D, N-1, E, E, Es...> {
    decltype(auto) operator()(const E& e, const Es&... es) {
       return static_cast<D&>(*this).exec(e, es...);
    }
    using OverloadImpl<D, N-1, E, E, Es...>::operator();
};

template<typename D, typename E, typename ...Es>
struct OverloadImpl<D, 0, E, Es...> { 
    decltype(auto) operator()() { 
       return static_cast<D&>(*this).exec();   
    }    
};

template<typename D, typename E, int N>
struct Overload : OverloadImpl<D, N, E>
{ };

, Overload exec.

template<typename K, typename V, int C>
struct M {
   template<typename ...T>
   M(T&&...) { }
};

template<typename K, typename V>
struct Entry {
   Entry(K, V) { }    
};

template<typename K, typename V>
struct CreateMapImpl : Overload<CreateMapImpl<K, V>, Entry<K, V>, 10> {
    template<typename ...T>
    M<K, V, sizeof...(T)> exec(const T&... t) {
       return { t... };   
    }
};

template<typename K, typename V>
CreateMapImpl<K, V> create_map{};

int main() {
   create_map<int, std::string>({1, "one"}, {2, "two"}, {3, "three"});   
}
+3

Source: https://habr.com/ru/post/1608144/


All Articles