Структурированная привязка, подобная кортежу, для внутреннего класса шаблона класса - PullRequest
0 голосов
/ 04 января 2019

Я хочу предоставить структурированную привязку для внутреннего класса шаблона класса. Как я могу специализироваться std::tuple_size для этого внутреннего класса?

Я не могу использовать структурированную привязку к элементу данных , потому что внутренний класс может быть типом, несовместимым с этой функцией. Поэтому мне нужно предоставить структурированное связывание типа кортежа . Чтобы предоставить такую ​​функцию внутреннему классу, мне нужно частично специализировать std::tuple_size в namespace std. Проблема в том, что я получил невыгруженный контекст для параметра T (внешнего класса).

Я знаю, что мог бы поместить внутренний класс в глобальное пространство имен и, таким образом, решить все проблемы, но есть ли способ получить тот же результат, сохраняя класс внутренним?

#include <tuple>

template<typename T>
class Collection
{
    public:
        struct Element
        {
            int id;
            T actual_element;
        };

    //...
};


namespace std 
{
    template<typename T>
    struct tuple_size<typename Collection<T>::Element> // Error! Non-deduced context
        : std::integral_constant<std::size_t, 2> {};
}



//Collection iterators...

int main()
{
    Collection<int> collection;

    for (auto & [id, element] : collection) //what I'd like to achieve
        //do some stuff...
}

1 Ответ

0 голосов
/ 04 января 2019

В этом случае необязательно указывать привязку: Element уже разложим, как:

struct Element { int i, j; };
auto [i, j] = Element{2, 3}; // ok

Однако, если предположить, что Element на самом деле более сложный и требует пользовательских привязок, тогда да - вам нужно будет его убрать. Тем не менее, не нужно , чтобы находиться в глобальном пространстве имен. Это может быть где-то еще:

namespace detail {
    template <typename T> struct Element { ... };
}

template<typename T>
class Collection
{
    public:
        using Element = detail::Element<T>;
        friend Element;
        // ...
};

И в этот момент специализировать привязки просто. В & dagger; нет никакого способа, поскольку, как вы указываете, специализация на Collection<T>::Element является не выводимым контекстом.

<час />

& dagger; Если не считать новой языковой функции, которая позволила бы вам включить структурированные привязки внутри самого тела класса. Для этого была такая бумага, P1096 , но она была отклонена при предъявлении. Что не означает, что новое предложение не может быть лучше.

...