简体   繁体   中英

Passing a vector with different types as initializer list to function

I have this none working code which should demonstrate what I want to achieve:

class Member
{
    const char * someText;
    union Parameter
    {
        const char * ptrParameter;
        double       doubleParameter;
        uint         uintParameter;
    };
};

class MyClass
{
    auto foo( std::vector<Member> & ) -> void;
};

int main()
{
    MyClass instance;

    instance.foo( 
        {
            { "SomeText", "TextParameter" },
            { "SomeDouble", 3.14159 },
            { "SomeUint",   32767 }
        }
                );
}

What I want to achieve:

  1. MyClass::foo expects a std::vector<Member> as parameter.
  2. This vector should be passed directly from an initializer list.
  3. The second parameter for Member can have different types which is here expressed with union Parameter .
  4. How can I detect in MyClass::foo which types have been passed?
  5. The types in union Parameter can be only these 3 as described.

I was trying a lot but no way I had success due to the fact I am a C++ beginner.


I am using C++17 - Boost is not an option. How can be this achieved?

You can get pretty close with std::variant :

class Member
{
    const char * someText;
    std::variant<const char *, double, unsigned int> parameter;
};

But you'll need a few additional changes to allow the type of initialisation you want:

  • The fields need to be public to allow aggregate initialisation (the compiler's built-in initialisation from { a, b } ), but class types have private fields by default. In this case, I would change class to struct .

  • auto foo( std::vector<Member> & ) -> void takes std::vector<Member> by lvalue reference, but you want to allow calling this with a temporary vector. In that case, I would not use a reference. I would take a std::vector<Member> by value.

  • { "SomeUint", 32767 } will not be a valid initialiser because 32767 has type signed int . It can be converted to both double and unsigned int and the compiler will not be able to figure out which one you want. You can write 32767u to have a constant of type unsigned int . (I'm assuming that's what your uint is a typedef for.)

How can I detect in MyClass::foo which types have been passed?

The best way for that depends on the reason you're doing it. If you'd like to execute different code based on the value being held, use visit . If you'd like to conditionally execute code for one type only, use get_if . If you'd just like to check, but do nothing with the value itself, use either index or holds_alternative .

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