Как передать член структуры / массива объединения в функцию - PullRequest
0 голосов
/ 29 сентября 2018

Например, я хочу отобразить значение только одного члена структуры / массива объединения, поэтому я хочу передать его в качестве аргумента в функцию, которая будет отображать только этот один член, а также будет отображать любой другой отдельный элемент, который я передаюв качестве аргумента.

#include <iostream>
using namespace std;

union ThreeTypes
{
    char letter;
    int whole;
    double real;
};

void showArr(ThreeTypes[], int); // ?? What parameters to pass?

int main()
{
    const int SIZE = 50;
    ThreeTypes arr[SIZE];
    for (int i = 0; i < SIZE; i++)
        arr[i].real = 2.37;

    showArr(arr, SIZE, ??? ); // what argument to pass to display member?

    return 0;
}
void showArr(ThreeTypes arr[],int size,???) // also, what parameters??
{
    for (int i = 0; i < size; i++)
        cout << arr[i].?? << endl; // member from argument????
}

Ответы [ 2 ]

0 голосов
/ 30 сентября 2018

В C ++ 17 вы должны использовать std::variant:

using ThreeTypes = std::variant<char, int, double>;

template <std::size_t N>
auto show_arr(std::array<ThreeTypes, N>& arr)
{
    for (auto& e : arr)
    {
        std::visit([](auto e) { std::cout << e << std::endl;}, e);
    }
}

auto test()
{
    std::array<ThreeTypes, 2> arr = {3.4, 'a'};

    show_arr(arr);
}
0 голосов
/ 29 сентября 2018

Одной из опций будет шаблонный тип указателя на элемент .Они обычно используются с типами class или struct, но также действительны с типом union.Тип указателя на член объявляется как MemberType ClassType::*pointer_name, а имя такого указателя можно использовать справа от оператора .* или ->*.

template <typename T>
void showArr(const ThreeTypes arr[], int size, T ThreeTypes::*ptr)
{
    for (int i = 0; i < size; ++i)
        std::cout << (arr[i].*ptr) << std::endl;
}

И вы создаетезначение указателя на член с синтаксисом &ClassType::member_name:

int main()
{
    const int SIZE = 50;
    ThreeTypes arr[SIZE];
    for (int i = 0; i < SIZE; i++)
        arr[i].real = 2.37;

    showArr(arr, SIZE, &ThreeTypes::real);
}

Еще один более общий вариант - взять вызываемый функтор:

template <typename F>
void showArr(const ThreeTypes arr[], int size, const F& func)
{
    for (int i = 0; i < size; ++i)
        std::cout << func(arr[i]) << std::endl;
}

Вы можете создатьфунктор для доступа к члену с помощью лямбды или std::mem_fn:

void print_reals_twice(const ThreeTypes arr[], int size)
{
    showArr(arr, size, [](const ThreeTypes& u) { return u.real; });
    // Same effects:
    showArr(arr, size, std::mem_fn(&ThreeTypes::real));
}

Но определение showArr таким образом также позволяет вам передать функтор, который делает что-то более сложное, чем просто возвратчлен, если хотите:

void print_sin2x_all(const ThreeTypes arr[], int size)
{
    showArr(arr, size, [](const ThreeTypes& u) { return std::sin(2*u.real); });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...