簡體   English   中英

C++ 部分模板特化:如何特化 std::iterator_category

[英]C++ partial template specialization: how to specialize std::iterator_category

我想編寫模板 function void foo() ,它需要 2 個迭代器或指針。

我想要一個專門用於 random_access_iterator 的版本。 我試着像下面這樣寫:

// generic version
template<class Iter, typename std::iterator_traits<Iter>::iterator_category>
void foo(Iter first, Iter last);

// Specialized version for random_access_iterator
template<class RandomIter>
void foo<RandomIter, std::random_access_iterator_tag>(RandomIter first, RandomIter last)
{
}

它給出錯誤:非法使用顯式模板 arguments

請讓我知道定義它的正確方法是什么。 謝謝

您不能部分專門化功能模板。 部分專業化僅適用於類模板。 您可以做的就是只有一個函數模板,該函數模板委派給適當專門化的類模板的static成員,例如

template <typename Iter,
          typename = typename std::iterator_traits<Iter>::iterator_category>
struct foo_impl {
    static void call(Iter first, Iter last);
};

template <typename Iter>
struct foo_impl<Iter, std::random_acces_iterator_tag> {
    static void call(Iter first, Iter last);
};

templlate <typename Iter>
void foo(Iter first, last) {
    foo_impl<Iter>::call(first, last);
}

或者,您可以使用部分排序。 在那種情況下,有兩個函數模板,一個以通用迭代器類別作為參數,另一個以特定類別作為參數。 類別或指向它的指針作為附加參數傳遞。 我認為這也需要轉發功能(我通常使用的方法是使用類模板的部分專業化方法)。

基於“標簽分發”模式,我為我的問題寫了一個解決方案:

// Using "= delete" on un-supported categories to get concise compile-time error information
template<typename Iter> void _foo(Iter first, Iter last, std::bidirectional_iterator_tag) = delete;

template<typename RandomIter>
void _foo(RandomIter first, RandomIter last, std::random_access_iterator_tag)
{ ... }

template<class Iter>
void foo(Iter first, Iter last)
{
    typename std::iterator_traits<Iter>::iterator_category category;
    _foo(first, last, category);
}

現在可以使用了。 如果有錯誤或需要改進,請發表評論。 謝謝。

作為對先前答案的補充,使用更新的 C++ 標准版本實現相同結果的方法。

C++17

您可以使用if constexpr

#include <iterator>
#include <type_traits>

template<class Iter>
void foo(Iter first, Iter last)
{
    using Cat = typename std::iterator_traits<Iter>::iterator_category;
    if constexpr (std::is_same_v<Cat, std::random_access_iterator_tag>) {
        // random access iterator
    }
    else if constexpr (std::is_same_v<Cat, std::bidirectional_iterator_tag>) {
        // bidirectional iterator
    }
    else if constexpr (std::is_same_v<Cat, std::forward_iterator_tag>) {
        // forward iterator
    }
    else if constexpr (std::is_same_v<Cat, std::input_iterator_tag>) {
        // input iterator
    }
}

C++20

您可以重載 function 並使用概念區分每種情況:

#include <iterator>

template<std::random_access_iterator Iter>
void foo(Iter first, Iter last)
{
    // random access iterator
}

template<std::bidirectional_iterator Iter>
void foo(Iter first, Iter last)
{
    // bidirectional iterator
}

template<std::forward_iterator Iter>
void foo(Iter first, Iter last)
{
    // forward iterator
}

template<std::input_iterator Iter>
void foo(Iter first, Iter last)
{
    // input iterator
}

暫無
暫無

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

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