Gunnar
Gunnar

Reputation: 313

How to get the number of elements in a struct?

I declared a struct for some options that shall be filled by command line arguments or by reading an input file:

struct options {
  int val1;
  int val2;
  bool val3;
}

Now I want to check for the correct number of arguments at execution of the program. Sure thing a

const int optionsSize = 3;

would do. But is there any adaptive way? What if I add another value into the struct and don't remember to increase the integer?

Upvotes: 6

Views: 10539

Answers (6)

Kaznov
Kaznov

Reputation: 1163

Even if it's not what would be the best option, since C++17 we can do template-meta-programming to get the information "how many members structure has", as long as the struct is an aggregate, non-polymorphic, and can be initialized using aggregate initialization.

Note, that unless you do some template-magic you shouldn't really use it.

In C++17 it's still pretty problematic, see https://gist.github.com/ChemiaAion/4118a3598f0b120b7f9c5884e9799a8b.

With C++20 you can do it using requires-expression:

struct UniversalType {
    template<typename T>
    operator T() {}
};

template<typename T>
consteval auto MemberCounter(auto ...Members) {
    if constexpr (requires { T{ Members... }; } == false)
        return sizeof...(Members) - 1;
    else
        return MemberCounter<T>(Members..., UniversalType{});
}

You can see this Reddit post to see discussion about it. It works by trying to instantiate aggregate initialization with more and more parameters, and if it fails it means, that there is one less member than current instantiation: sizeof...(Members) - 1.

I'm not the author of the provided code. For anyone interested, here are some more links related to the topic:

Upvotes: 8

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145204

"What if I add another value into the struct and don't remember to increase the integer?"

Then the unit testing is rather deficient if it doesn't detect that.

Cheers & hth.,

Upvotes: 0

sbi
sbi

Reputation: 224009

This would require reflection, which C++ doesn't have.

So in your case, the code that parses the command line, checks for syntax errors, and sets the requested values in your struct will also have to check whether enough values are set.

Upvotes: 5

Nim
Nim

Reputation: 33655

I am not aware of any way of determining the number of members in a struct at runtime. You have two options:

  1. Use a boost fusion sequence, but this is overkill
  2. Use boost program_options, and here for each option I believe you can specify whether it should be mandatory or not. And this will automatically check for you (while parsing the command line). So all you need to remember to do is to add the struct member to the set of options for program_options. There are lots of examples in the docs, ask if you have any issues...

Upvotes: 0

Helmut Grohne
Helmut Grohne

Reputation: 6768

There is no way to compute this number inside the language. Basically your only option is to write a script to look at the source. If all the elements in your struct have the same type, you can use sizeof(thestruct)/sizeof(commontype).

Upvotes: 1

RC.
RC.

Reputation: 28197

Why not add the options as specified into an std::vector<string> options and use the options.size() method to check the correct number. Then convert them to the proper datatype.

A more robust way of doing this kind of thing would be to use Boost Program Options

Upvotes: 11

Related Questions