/ / Rzuć klasę wielu szablonów w parametrze szablonu szablonu - wiązanie szablonu? - c ++, szablony, szablony szablonów

Rzuć klasę wielu szablonów w parametrze szablonu szablonu - powiązanie szablonu? - c ++, szablony, szablony szablonów

Biorąc pod uwagę następującą klasę:

template <class T, template <typename> class B>
class A { B<T> b; };

Teraz mogę pisać taki kod:

A<float, MyVector> a1;
A<int, MySet> a2;

Jaki jest najbardziej elegancki sposób umieszczania klas wieloparametrowych, których wszystkie parametry są określone oprócz jednej, w B? Jak mapa z kluczami wewnętrznymi? Jedyne, co mogę wymyślić, to:

template <class U> using C = MyMap<int, U>;
A<float, C<int>> a3;

Czy istnieje taki szablon równoważny do std ::bind, gdzie możemy podać tylko część parametrów i pozostawić jeden z nich otwarty? Jestem pewien, że język tego nie przewiduje, ale ludzie musieli to wcześniej rozwiązać.

A<float, MyMap<int, _>> a3;

Odpowiedzi:

4 dla odpowiedzi № 1

Nie ma wbudowanego szablonu równoważnego z std::bind, ale możesz sam napisać. Oto prosta wersja, która wiąże pierwszy argument szablonu, który można rozszerzyć w celu dostosowania do własnych potrzeb:

template <typename T, template <typename...> class B>
struct bind_t1 {
template <typename... Ts>
using type = B<T,Ts...>;
};

Więc po prostu użyj bind_t1 jak na przykład:

A<float, bind_t1<int, std::map>::type> a3;

Zwróć uwagę, że na przykład będziesz musiał zmodyfikować parametry szablonu, aby przyjąć szablon z różnymi szablonami:

template <class T, template <typename...> class B>
class A { B<T> b; };

Oto nieco rozszerzona wersja, która może wiązać szereg ciągłych elementów na początku listy parametrów:

template <template <typename...> class B, typename... Ts>
struct bind_nt1 {
template <typename... Us>
using type = B<Ts...,Us...>;
};

//Usage
A<std::less<int>, bind_nt1<std::map, int, float>::type> a3;

Oto ogólna wersja oparta na sposobie std::bind robi rzeczy. Nie przeprowadza żadnej weryfikacji i prawdopodobnie ma pewne skrajne przypadki, ale jest dobrym punktem wyjścia. Dzięki Piotr Skotnicki do ulepszeń.

template <std::size_t N>
struct placeholder{};

template <template <typename...> class B, typename... Ts>
struct bind_t {
private:
template <typename T, typename UTuple>
struct resolve_placeholder {
using type = T;
};

template <std::size_t N, typename UTuple>
struct resolve_placeholder<placeholder<N>, UTuple> {
using type = typename std::tuple_element<N-1, UTuple>::type;
};

public:
template <typename... Us>
using type = B<typename resolve_placeholder<Ts, std::tuple<Us...>>::type...>;
};


//Usage
A<int, bind_t<std::map, float, placeholder<1>, std::less<float>>::type> a3;

Dzięki temu możesz nawet zmienić kolejność parametrów szablonu:

//std::map<int,float>
bind_t<std::map, placeholder<2>, placeholder<1>>::type<float, int> b;