I like writing checks for a function over a list. For this I usually write a function like this:
inline bool good_strings(const std::vector<const char *> & items)
{
for (i in items) {
if (not is_good(i)) return false;
}
return true;
}
Then I can write like if (all_good({"a", "b", "c", "d", "e"})) {...}
and it looks really nice. This is good to use when your check for a couple of items grows bigger like this:
if (is_good("a") and is_good("b") and /* that's too much, man */ is_good("c")) {...}
But I'm concerned with the overhead of the container I'm using, and also it's hard to choose one: std::vector
, std::list
, QList
, QStringList
or maybe even std::array
or std::initializer_list
- which should be used for inline functions? And which of these a has minimum or even zero overhead when creating using the {}
brackets?
Alright, and update: I grabbed my friend licensed IDA Pro and checked some options.
std::initializer_list
: the function doesn't even inline, and there
is overhead for creating the list and copying pointers.std::vector
: the function does inline, however, there is an
overhead for creating a vector and copying pointers there.std::array
: not as good-looking because of template specialization,
and the function doesn't inline. So calling it many times creates
many similar chunks of code. However, there is no overhead for array
creation, and all pointers are passed as function parameters, which
is fast for x86_64
register calling a convention.The question remains, is there an absolutely zero-cost container?
None of the containers are going to be zero overhead. std::array
or std::initializer_list
will give you the least amount of cost though. std::array
needs it's type and size specified at compile time so it is a little less user friendly then a std::initializer_list
in this case. So, using a std::initializer_list<const char*>
will be the smallest and easiest to use "container" you can use. It will cost the size of the array of pointers the compiler generates and possibly a little more and it won't require any dynamic memory allocation.
If you can use C++17 You don't even need a container. Utilizing a variadic template and a fold expression you can have all the arguments passed to the function as separate parameters and the apply the same operation to all of the arguments.
template<typename... Args>
bool good_strings(Args&&... args)
{
return (is_good(args) && ...);
}
will turn
all_good("a", "b", "c", "d", "e")
into
return is_good("a") && is_good("b") && ... && is_good("e");
which leverages short circuiting so it will stop evaluating as soon as the first call to is_good
returns false.
You can utilize the variadic template in C++11, but you would either need to use recursion, or build your own array, which really doesn't gain you anything with the extra complexity you would have.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With