16

Iteratorテンプレートパラメータをそのパラメータで特殊化することは可能value_typeですか?

次のプロトタイプの関数があります。

template<typename InputIterator>
void f(InputIterator first, InputIterator last);

InputIterator::value_typeそして、もしそうなら特別に扱いたいSomeSpecificType.

4

5 に答える 5

10

いくつかの中間構造体を使用して、必要な部分的なテンプレートの特殊化を取得できます。このような何かがトリックを行う必要があります

template<typename T, typename V>
struct f_impl
{
  static void f( T first, T last ) {...}; //Default version
};

template<typename T>
struct f_impl<T, SomeSpecificType>
{
   static void f(T first,T last) {...}; //Specialisation
};

template<typename InputIterator> void f(InputIterator first, InputIterator last)
{
  f_impl<
      InputIterator,
      typename std::iterator_traits<InputIterator>::value_type
  >::f(first,last);
};
于 2011-06-08T03:20:36.130 に答える
8

SFINAEを使用してenable_if[_c]、とis_sameがBoostまたは(およびいずれかまたはそれぞれ<type_traits>で適切に修飾されている)のいずれかであると想定します。boost::std::

template<typename InputIterator>
typename enable_if<
    !is_same<
        typename std::iterator_traits<InputIterator>::value_type,
        SomeSpecificType
    >::value
>::type
f(InputIterator first, InputIterator last)
{
    // Default implementation.
}

template<typename InputIterator>
typename enable_if<
    is_same<
        typename std::iterator_traits<InputIterator>::value_type,
        SomeSpecificType
    >::value
>::type
f(InputIterator first, InputIterator last)
{
    // Special case
}

ブーストの場合はboost::enable_if_c、上記のようなものに使用してください。あなたは使用boost::enable_ifして取り除くことができます::valueが、それからまた例えばを使用しなければなりませんboost::disable_if

于 2011-06-08T03:25:04.450 に答える
0

どうですか:

template<typename T>
typename std::enable_if<std::is_same<typename T::value_type, SomeType>::value, void>::type
f(T first, T second);
于 2011-06-08T03:20:52.827 に答える
0

これは機能します。このタイプの特殊化は構造体でのみ機能するため、関数でこれを行うことはできません。

template <typename InputIterator, typename ValueType = typename InputIterator::value_type>
struct foobar
{
    static void invoke(InputIterator first, InputIterator second)
    {
        // ...
    }
};

template <typename InputIterator>
struct foobar<InputIterator, SomeSpecificType>
{
    static void invoke(InputIterator first, InputIterator second)
    {
        // ...
    }
};

タイプを設定する必要はありません。自動的に推測されます。

于 2011-06-08T03:26:27.483 に答える
0

私をナイーブと呼んでください、しかしなぜ次のもので十分ではないのですか?

struct MyType; // the only type I want

#include <iterator>
typedef std::iterator<std::input_iterator_tag, MyType> MyIt;

void f(const MyIt & begin, const MyIt & end)
{
   /* ... */
}

OK、上記のことを忘れてください、それはナンセンスでした。これを行う方法は次のとおりです。これは、C++0xに対するLucの上記の正解です。

#include <vector>
#include <iterator>
#include <type_traits>

// "int" is our desired iterator value type, "void" is f's return type.
template <typename It>
typename std::enable_if<std::is_same<int, typename std::iterator_traits<It>::value_type>::value, void>::type
f(const It & begin, const It & end) { /* your function here */ }

int main()
{
  std::vector<double> x;
  std::vector<int> y;

  //f(x.cbegin(), x.cend()); // error
  f(y.cbegin(), y.cend());   // works
}
于 2011-06-08T03:39:30.153 に答える