-1

重複の可能性:
デフォルトのテンプレート パラメータとして enable_if イテレータ?

std::iterator_traits<T>::value_typeが有効で定義されているかどうかをコンパイル時に知るための解決策を探しています。これに関する問題は、std ライブラリが value_type の宣言を T の派生型に転送することです。

typedef T::value_type value_type;

value_type が存在しないことに関連するエラーを回避するために、コンパイル時に T::value_type が有効な型であるかどうかを知る必要があります。

次の例を検討してください。

std::iterator_traits<int *>::value_type; // OK - should return that value_type exists as it's defined in specialization of std::iterator_traits

std::iterator_traits<const int *>::value_type; // OK - should return that value_type exists as it's defined in specialization of std::iterator_traits

std::iterator_traits<std::vector<int>::const_iterator> >::value_type; // OK - the value_type exists defined within std::vector<int>::const_iterator

std::iterator_traits<int>::value_type; // ERROR - the value_type is not defined within int class - this is what I'm trying to avoid to resolve the value_type of.

C++ 標準および std ライブラリ標準に完全に準拠し、コンパイラに依存しないソリューションが必要です。

4

2 に答える 2

0

問題は、これに関するコメントのアプローチで示すことができます。

#include <iterator>
#include <iostream>

template <typename T>
class IsIterator {
public:
  struct TrueValue {
  char val;
 };

 struct FalseValue {
   char val[2];
 };

template <typename U>  
 static TrueValue evaluateIsIter(typename U::iterator_category*);

 template <typename U>
 static FalseValue evaluateIsIter(...);

 static const bool value = sizeof(evaluateIsIter<T>(0)) == sizeof(TrueValue);
};


int _tmain(int argc, _TCHAR* argv[])
{
std::cout << IsIterator< int >::value << std::endl;
std::cout << IsIterator< std::iterator_traits<int> >::value << std::endl;
return 0;
 }

VS2005 コンパイラでの結果: 0 1

これでは、問題を解決するには不十分であることがわかります。それとも私は何か間違ったことをしていますか?

于 2012-08-14T15:19:11.807 に答える
0

解決策はこれですが、カスタム定義の反復子には、特殊化された std::iterator_traits クラスだけでなく、クラス内で定義された typedef が必要であるという欠点があります。

// IsIterator.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <iterator>
#include <iostream>
#include <vector>

template <typename T>
class ExtractType {
public:
  typedef T Result;  
};

template <typename U>
class ExtractType<std::iterator_traits<U> >
{
public:
  typedef U Result;
};

template <typename T>
class IsIteratorPointer
{
public:
  static const bool value = false;
};

template <typename T>
class IsIteratorPointer<T*>
{
public:
  static const bool value = true;
};

template <typename T>
class IsIteratorPointer<const T*>
{
public:
  static const bool value = true;
};

template <typename T>
class IsIterator {
public:
  struct TrueValue {
    char val;
  };

  struct FalseValue {
    char val[2];
  };

  template <typename U>  
  static TrueValue evaluateIsIter(typename U::iterator_category*);

  template <typename U>
  static FalseValue evaluateIsIter(...);

  typedef typename ExtractType<T>::Result TestType;

  static const bool value = IsIteratorPointer<TestType>::value || sizeof(evaluateIsIter<TestType>(0)) == sizeof(TrueValue);
};

struct Foo {  
};

template <> 
struct std::iterator_traits<Foo>
{
  typedef random_access_iterator_tag iterator_category;
};

int _tmain(int argc, _TCHAR* argv[])
{
  std::cout << IsIterator< int >::value << std::endl;
  std::cout << IsIterator< std::iterator_traits<int> >::value << std::endl;
  std::cout << IsIterator< std::iterator_traits<int*> >::value << std::endl;
  std::cout << IsIterator< std::iterator_traits<Foo> >::value << std::endl; // Will be 0 (only drawback) - typedef must be in Foo directly
  std::cout << IsIterator< std::vector<int>::const_iterator >::value << std::endl;

    return 0;
}

疑問が残ります: この欠点はどうにかして取り除くことができるでしょうか?

于 2012-08-14T15:45:51.623 に答える