template <typename InputIterator>
MyFun(const InputIterator begin, const InputIterator end)
{
// I want to static_assert that decltype(*begin) == SomeType
}
我怎样才能做到这一点?我在想static_assert(std::is_same<*InputIterator,SomeType>)
,但这当然行不通...
template <typename InputIterator>
MyFun(const InputIterator begin, const InputIterator end)
{
// I want to static_assert that decltype(*begin) == SomeType
}
我怎样才能做到这一点?我在想static_assert(std::is_same<*InputIterator,SomeType>)
,但这当然行不通...
static_assert(is_same<typename std::iterator_traits<InputIterator>::value_type,
SomeType>::value, "");
另一种使用decltype
, 附带说明它通常会产生引用(但可能不会!)。
// 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, "");
我宁愿使用std::is_convertible
而不是std::is_same
和const SomeType&
而不是SomeType
因为通常情况下,const SomeType&
我们需要迭代器的可转换性。
static_assert(
std::is_convertible<decltype(*begin), const SomeType&>::value,
"Input parameters must be iterators over objects convertible to 'SomeType'."
);
此外,如果要通过迭代器修改数据,const SomeType&
则应更改为。SomeType&
这在继承的情况下非常有用,其中子对象上的迭代器被传递给接收父类的迭代器的函数。
这是一个具体的例子:
#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;
}