简体   繁体   中英

How to initialize POD struct with private/protected members without creating constructor?

POD can have private/protected members

Because of protected members, it is impossible to initialize struct like this:

struct SomePOD_t {
protected:
    char *p_begin;
    char *p_end;
};

void foo() {
    const char *STR = "Some data";
    SomePOD_t data = { STR, STR + strlen(STR)+1 }; // error "no mathing constructor for
                                                   // initialization of SomePOD_t"
}

My question is how to make easier passing POD types to functions:

// gonna use this foo
void foo_uses_some_pod(SomePOD_t data);

void foo()
{
     const char *STR = "Some data";

      //error "no matching function for call to 'foo_uses_some_pod'"
      // "candidate function not viable: cannot convert initializer list argument to 'SomePOD_t'"
     foo_uses_some_pod({STR, STR + strlen(STR)+1});

     //ok, if SomePOD_t::static_built_function is defined.
     foo_uses_some_pod(SomePOD_t::static_built_function(STR, STR + strlen(STR)+1)); 
}

I think explicit type mapping SomePOD_t{STR, STR + strlen(STR)+1} in the function call is a good practice, but excess static_built_function in SomePOD_t::static_built_function(STR, STR + strlen(STR)+1) is too much.

If I add constructor to SomePOD_t it will not be POD anymore, so all types, that use SomePOD_t will become non-POD too and I have to add constructors for every type with SomePOD_t as member, or type with type that has type ... ... that has SomePOD_t as member.

Can type be POD, have private/protected members and support initializer-list inititalization? How?

Things have changed over time. More recent specifications of the C++ language have deprecated the concept of a "POD" class. There is now the idea of an "aggregate". Aggregates cannot have protected or private members, nor can they have non-default constructors. The initialization you are trying with an initializer list can be applied to aggregates.

Since you have protected members, aggregate initialization does not apply. If you want to construct the object with an initializer list you need to provide a constructor to do so.

The requirements for POD class regarding constructors are:

  • Has one or more default constructors, all of which are either trivial or deleted, and at least one of which is not deleted.

  • Every copy constructor is trivial or deleted

  • Every move constructor is trivial or deleted

  • Every copy assignment operator is trivial or deleted

  • Every move assignment operator is trivial or deleted

  • at least one copy constructor, move constructor, copy assignment operator, or move assignment operator is non-deleted

Those restrictions are only on the special constructors listed above (namely default constructors and copy/move constructors). That said, you can have other user-defined constructors.

Example:

#include <iostream>
#include <type_traits>

struct SomePOD_t {
private:
    int a;
    int b;

public:
    // Note that "= default" is required here; 
    // otherwise the default constructor wouldn't be defined.
    SomePOD_t() = default;
    SomePOD_t(int a, int b) : a(a), b(b){}
};

void foo(SomePOD_t pod) { }

int main(int argc, char** args)
{
    std::cout << std::boolalpha;
    std::cout << std::is_pod<SomePOD_t>::value << std::endl; // true
    foo({1, 2});
    return 0;
}

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