template <typename InputIterator>
MyFun(const InputIterator begin, const InputIterator end)
{
// I want to static_assert that decltype(*begin) == SomeType
}
How can I do this? I'm thinking static_assert(std::is_same<*InputIterator,SomeType>)
but that of course does not work...
static_assert(is_same<typename std::iterator_traits<InputIterator>::value_type,
SomeType>::value, "");
An alternative using decltype
, with a note in passing that it often produces a reference (but may not!).
// If you want to assert that the dereferenced item is indeed a reference
static_assert(std::is_same<decltype(*begin), SomeType&>::value, "");
// If you are only interested in the "bare" type
// (equivalent to Jesse's providing iterator_traits was properly specialized)
static_assert(std::is_same<
typename std::remove_reference<decltype(*begin)>::type,
SomeType
>::value, "");
I would rather use std::is_convertible
instead of std::is_same
and const SomeType&
instead of SomeType
because usually, the convertibility to const SomeType&
is all we need from the iterator.
static_assert(
std::is_convertible<decltype(*begin), const SomeType&>::value,
"Input parameters must be iterators over objects convertible to 'SomeType'."
);
In addition, const SomeType&
shall be changed to SomeType&
if the data is going to be modified through the iterators. This is essentially useful in case of inheritance where iterators over child objects are passed to a function receiving iterators of parent class.
Here is a concrete example:
#include <type_traits>
#include <vector>
#include <iostream>
struct Animal {
int x;
inline void print() const {
std::cout << "x = " << x << std::endl;
}
inline int modify() {
return ++x;
}
virtual ~Animal() = default;
};
struct Cat: public Animal {
};
struct Dog: public Animal {
};
template<typename I>
inline void printAnimals(I begin, I end) {
static_assert(
std::is_convertible<decltype(*begin), const Animal&>::value,
"Input parameters must be iterators over objects of type 'Animal'."
);
for (I it = begin; it != end; ++it) {
const Animal& a = *it;
a.print();
}
std::cout << "---------" << std::endl;
}
template<typename I>
inline void modifyAnimals(I begin, I end) {
static_assert(
std::is_convertible<decltype(*begin), Animal&>::value,
"Input parameters must be iterators over objects of type 'Animal'."
);
for (I it = begin; it != end; ++it) {
Animal& a = *it;
a.modify();
}
}
int main() {
std::vector<Dog> dogs(2);
dogs[0].x = 10;
dogs[1].x = 20;
printAnimals(dogs.begin(), dogs.end());
modifyAnimals(dogs.begin(), dogs.end());
printAnimals(dogs.begin(), dogs.end());
std::vector<Cat> cats(3);
cats[0].x = 100;
cats[1].x = 110;
cats[2].x = 120;
printAnimals(cats.begin(), cats.end());
modifyAnimals(cats.begin(), cats.end());
printAnimals(cats.begin(), cats.end());
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.