简体   繁体   中英

Is there a way to store multiple types of struct members pointers

I have this code who's working just fine to retrieve the foo members by index.

#include <string>
#include <iostream>

struct Foo {
    int a = 42;
    int b = 16;
    std::string str = "hi";
};

int main()
{
    int Foo::*members[] = { &Foo::a, &Foo::b };
    Foo foo;

    std::cout << foo.*members[1] << std::endl;
    return 0;
}

The problem is that I have an std::string on my struct that I want to be able to access the same way, is there a solution scalable to any type?

What I've tried:

#include <string>
#include <iostream>
#include <any>

struct Foo {
    int a = 42;
    int b = 16;
    std::string str = "coucou";
};

int main()
{
    std::any Foo::*members[] = { (std::any Foo::*)&Foo::a, (std::any Foo::*)&Foo::b, (std::any Foo::*)&Foo::str };
    Foo foo;

    std::cout << std::any_cast<int>(foo.*members[0]) << std::endl;
    return 0;
}

I told myself that if store an array of std::any , that will work. In fact, this code does compile but crashes.

Any solutions?

You might use std::tuple :

std::tuple members{&Foo::a, &Foo::b, &Foo::str }; // C++17 CTAD
                                                  // else, use `std::make_tuple`
Foo foo;

std::cout << foo.*std::get<0>(members) << " " << foo.*std::get<2>(members) << std::endl;

Demo

(I'll first say I agree with @MarekR's comment, that your question is likely an "XY problem" and you probably don't actually want to do this at all... but still:)

This is an interesting challenge - and one which has been tackled by the "crazy genius" Antony Polukhin, in his magic_get library - providing you are using the C++14 language standard, or later.

There is actually no need to store anything! The struct definition itself has all the information you need. Thus, when you write:

#include <iostream>
#include <string>

#include "boost/pfr.hpp" // <- Not formally a part of Boost, yet...
                         //    you'll need to download the library from github

struct Foo {
    int a = 42;
    int b = 16;
    std::string str = "hi";
};

int main() {
    Foo my_foo;

    std::cout 
        << "a is " << boost::pfr::get<0>(my_foo) << ", "
        << "b is " << boost::pfr::get<1>(my_foo) << ", "
        << "and str is \"" << boost::pfr::get<2>(my_foo) << "\".\n";
}

you get:

a is 42, b is 16, and str is "hi".

just like you wanted.

To understand what the hell is going on, and where this black magic comes from, watch Antony's 2018 talk:

Better C++14 reflections - Antony Polukhin - Meeting C++ 2018

Try not to use a string as a pointer inside the Struct because it will not be pointing to nothing. Instead you can simply use like this:

    std::cout << foo.str << std::endl;

It will output your string as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM