簡體   English   中英

我如何 static_assert 迭代器取消引用的類型?

[英]How do I static_assert the type that an iterator dereferences to?

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>)但這當然不起作用......

std :: iterator_traits

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_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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM