можно вывести тип элемента кортежа в параметре функции (ie с помощью std :: tuple_element)? - PullRequest
0 голосов
/ 27 марта 2020

У меня есть структура, которая хранит некоторые данные в кортеже. Я хочу построить функцию getWithDefault<n>(m), которая получает данные из n-го члена, но заменяет их на m, если значение равно 0. Но для этого мне нужно знать правильный тип данных для m в параметре функции: getWithDefault<>(WhichType?). Есть ли способ сделать это? Я пробовал с std::tuple_element, но, похоже, он не работает.

#include <iostream>
#include <tuple>


template <typename... T>
struct C
{
    C(T... args) : t(std::make_tuple(args...)) {}

    template <int n>
    auto get() const
    { return std::get<n>(t); }

    template <int n>
    auto getWithDefault(std::tuple_element<n, decltype(t)>::type de)    // Compiler error: identifier not found
    {
        const auto v = get<n>();
        return v != 0 ? v : de;
    }

private:

    const std::tuple<T...> t;
};



int main()
{

    C<int, int> c(0, 4);

    std::cout << c.getWithDefault<0>(5);     // this should return 5

    return 0;
}

Я понимаю, почему этот код не работает - std::tuple_element не имеет доступа к переменной-члену изнутри параметр функции. Итак, существует ли реальный способ определения типа термина кортежа из параметра функции?

Ответы [ 2 ]

2 голосов
/ 27 марта 2020

Нет необходимости выводить тип, потому что вы его уже знаете. Возможно, вы ссылаетесь на использование decltype, но вам это тоже не нужно (можно, но не нужно). В любом случае ...

Для удобства вы можете использовать шаблон псевдонима:

template <size_t n>
using nth_type = typename std::tuple_element<n,std::tuple<T...>>::type;

Полный пример:

#include <iostream>
#include <tuple>


template <typename... T>
struct C
{
    C(T... args) : t(std::make_tuple(args...)) {}


    template <size_t n>
    using nth_type = typename std::tuple_element<n,std::tuple<T...>>::type;
    template <int n>
    auto get() const
    { return std::get<n>(t); }

    template <size_t n>
    auto getWithDefault(nth_type<n> de)    
    {
        const auto v = get<n>();
        return v != 0 ? v : de;
    }

private:

    const std::tuple<T...> t;
};



int main()
{

    C<int, int> c(0, 4);

    std::cout << c.getWithDefault<0>(5);     // this should return 5

    return 0;
}
1 голос
/ 27 марта 2020

У вас просто есть порядок объявления декларации (и пропущенный typename), переместите t до getWithDefault:

template <typename... T>
struct C
{
private:
    const std::tuple<T...> t;

public:
    C(T... args) : t(std::make_tuple(args...)) {}

    template <int n>
    auto get() const
    { return std::get<n>(t); }

    template <int n>
    auto getWithDefault(std::tuple_element_t<n, decltype(t)> de)
    {
        const auto v = get<n>();
        return v != 0 ? v : de;
    }

};

Демо

...