2
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>),但这当然行不通...

4

3 回答 3

9

std::iterator_traits

static_assert(is_same<typename std::iterator_traits<InputIterator>::value_type, 
               SomeType>::value, "");
于 2013-10-15T04:52:28.147 回答
3

另一种使用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, "");
于 2013-10-15T06:44:24.383 回答
0

我宁愿使用std::is_convertible而不是std::is_sameconst 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;
}
于 2021-11-16T11:05:53.447 回答