Форсировать невыведенный контекст - type_identity и т. Д. - PullRequest
1 голос
/ 01 августа 2020

Я пытаюсь создать шаблон, который выводит тип, связанный с одним параметром шаблона, в то время как другие типы обрабатываются в невыведенном контексте. Ниже приведен минимальный пример. Я могу делать то, что ищу, используя два контекста вывода, но можно ли это сделать в одном? Я думал, что попробую использовать что-то вроде type_identity, но мне не повезло.

Живой пример: https://onlinegdb.com/By0iDOM-P

template<size_t... Idx, size_t s>
void foo(index_sequence<Idx..., s>) {
    cout << s << endl;
}

template<typename T>
struct TypeIdentity {
    using Type = T;
};

template<typename T>
using Identity = typename TypeIdentity<T>::Type;

template<typename... Idx, size_t s>
void bar(index_sequence<Identity<Idx>{}..., s>) {
    cout << s << endl;
}

template<size_t s>
void baz(index_sequence<0, s>) {
    cout << s << endl;
}

template<size_t... Idx>
struct Qux {
    template<size_t s>
    static void qux(index_sequence<Idx..., s>) {
        cout << s << endl;
    }
};

int main()
{
    foo<0>(make_index_sequence<2>{}); // couldn't deduce template parameter ‘s’
    bar<integral_constant<size_t, 0>>(make_index_sequence<2>{}); // couldn't deduce template parameter ‘s’
    baz(make_index_sequence<2>{});
    Qux<0>::template qux(make_index_sequence<2>{});

    return 0;
}

1 Ответ

0 голосов
/ 01 августа 2020

Нет. Проблема в том, что пакет Idx... слишком жадный, чтобы оставить что-нибудь на s. Вы можете использовать s, Idx..., чтобы получить первое значение, но вы не можете использовать Idx..., s, чтобы получить последнее. TypeIdentity в этом вам не поможет, и вам понадобятся другие уловки.

Например, распаковка в массив (C ++ 14):

template<std::size_t first, std::size_t... rest>
void foo(std::index_sequence<first, rest...>) {
    const std::size_t indices[]{first, rest...};
    const std::size_t last = indices[sizeof...(rest)];

    std::cout << last << std::endl;
}

или использование кратное выражение с оператором запятой (C ++ 17):

template<std::size_t first, std::size_t... rest>
void foo(index_sequence<first, rest...>) {
    const std::size_t last = (first, ..., rest);
    std::cout << last << std::endl;
}

Я изолировал first, чтобы убедиться, что весь пакет first, rest... никогда не бывает пустым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...