Reputation: 4928
Suppose I have a class with std::vector<bool> a
and std::vector<int> b
fields that I want to reserve()
in a constructor to some size which is equal for both containers. Given that reserve()
accepts size_type
parameter, to be fully safe, I have to - from what I understand - write my constructor using two parameters, which is not particularly appealing:
MyCtor(std::vector<bool>::size_type size1, std::vector<int>::size_type size2)
{
abortIfNotEqual(size1, size2); // Proceed only if size1 == size2
a.reserve(size1);
b.reserve(size2);
}
From what I've read, size_type
is usually the same as size_t
, at least for standard containers, so I could probably do this without ever encountering any potential problems:
MyCtor(std::size_t size)
{
a.reserve(size); // More readable, but is this always ok?
b.reserve(size);
}
However, is there a better, safer way to strictly use size_type
without having to access it via a specific container<T>
for a specific type T
?
Having to use a specific container<T>
is also rather annoying when e.g. accessing an element: for a[i]
, i
has to be std::vector<bool>::size_type
, as I assume that using e.g. unsigned int i
would be less safe.
Is there a common, universal, more readable way to go in such situations? Or should I simply use size_t
or even unsigned long int
and forget about this?
Upvotes: 4
Views: 172
Reputation: 1575
I'd have the function accept the smaller of the two types. In C++11, this can be done via:
#include <vector>
#include <type_traits>
#include <limits>
typedef std::vector<bool>::size_type boolType;
typedef std::vector<int>::size_type intType;
typedef std::conditional<(std::numeric_limits<boolType>::max() <
std::numeric_limits<intType>::max()),
boolType,
intType>::type smallerSizeType;
MyCtor(smallerSizeType size)
{...}
Lacking C++11, you can manually define your own version of std::conditional
and replace std::numeric_limits<boolType>::max()
with static_cast<boolType>(-1)
, etc..
Upvotes: 1
Reputation: 5871
Since the primary component of your question is how do you ensure your safety while just assuming the size types are the same, I would recommend static_assert std::is_same. This compiles with c++17:
Simplifying the notation was important, so here, I typedef a size_type on this class, and internally make sure it is the same as both of the size types it is representing. If they don't match, it is a compile time error.
#include <vector>
class MyCtor {
std::vector<bool> a;
std::vector<int> b;
typedef std::vector<bool>::size_type st1;
typedef std::vector<int>::size_type st2;
static_assert(std::is_same<st1, st2>::value);
public:
typedef st2 size_type;
MyCtor(size_type s1, size_type s2) {}
};
Special thanks to this stack overflow answer: How to check if two types are same at compiletime(bonus points if it works with Boost strong typedef) which also includes the c++11 workaround.
Upvotes: 3