Reputation: 38919
I am working in a C++03 project. And I'm taking an iterator into a template. I need to assert that this iterator references a specific type. Does C++ provide me a way to do this beyond writing my own struct for validation?
What I want is the equivalent of this C++14 functionality:
static_assert(is_same<iterator_traits<InputIterator>::value_type, int>(), "Not an int iterator");
Since it's C++03 I assume that I'll have to use an assert
and that's fine if it's a runtime only debug check I just need the check to be there.
Upvotes: 2
Views: 277
Reputation: 38919
Since the parameters of the question are:
A way to do this beyond writing my own struct for validation
And it is assumed:
I'll have to use an
assert
and that's fine if it's a runtime only debug check
You can use typeid
in C++03:
assert(typeid(iterator_traits<InputIterator>::value_type) == typeid(int));
Upvotes: 0
Reputation: 303107
C++03 doesn't come with a static_assert
-type thing, that's a C++11 feature. However, there's BOOST_STATIC_ASSERT
. If Boost is not available to you, then this is actually a fairly straightforward thing to write:
namespace detail {
template <bool > struct my_static_assert;
template <> struct my_static_assert<true> { };
template <size_t > struct my_tester { };
}
#define MY_STATIC_ASSERT(B) \
typedef ::detail::my_tester< sizeof(::detail::my_static_assert< ((B) == 0 ? false : true) >)> \
my_static_assert_typedef_ ## __COUNTER__ __attribute__((unused))
The idea is that, we take our expression B
, convert it to a bool
, and use that in a context where if it's true
, we'll have a complete type, and if it's false
, we won't. You cannot take sizeof()
an incomplete type, so that'll be a compile error.
So if I did:
MY_STATIC_ASSERT(sizeof(int) >= 5);
gcc gives me:
main.cpp: In function 'int main()':
main.cpp:9:92: error: invalid application of 'sizeof' to incomplete type 'detail::my_static_assert<false>'
typedef detail::my_tester< sizeof(detail::my_static_assert< ((B) == 0 ? false : true) >)> \
^
main.cpp:15:5: note: in expansion of macro 'MY_STATIC_ASSERT'
MY_STATIC_ASSERT(sizeof(int) >= 5);
^
It's not quite as nice as:
main.cpp:15:5: error: static assertion failed:
static_assert(sizeof(int) >= 5, "");
^
but then, that's what happens when you don't have a language feature.
With that, we can convert:
static_assert(std::is_same<std::iterator_traits<InputIterator>::value_type, int>(),
"Not an int iterator");
To:
namespace details {
template <typename T, typename U>
struct is_same { static const bool value = false; };
template <typename T>
struct is_same<T, T> { static const bool value = true; };
}
MY_STATIC_ASSERT(details::is_same<
std::iterator_traits<InputIterator>::value_type, int
>::value); // Not an int iterator
iterator_traits
already existed in C++03, and adding a comment will let the message show up in the compile error.
Upvotes: 3