如何知道是否定义了std :: iterator_traits <t> :: value_type </t>

时间:2012-08-14 09:34:49

标签: c++ templates std

  

可能重复:
  enable_if iterator as a default template parameter?

我正在寻找解决方案,以便在编译时知道std::iterator_traits<T>::value_type是否有效且已定义。这个问题是std库将value_type的声明转发到T:

中的派生类型
typedef T::value_type value_type;

我需要知道T :: value_type在编译时是否是有效类型,以避免与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库标准和独立于编译器。

2 个答案:

答案 0 :(得分: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

可以看出,这还不足以解决问题。或者我做错了什么?

答案 1 :(得分:0)

解决方案就是这样,但缺点是自定义的迭代器类必须在类中定义typedef,而不仅仅是专门的std :: iterator_traits类。

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

现在的问题仍然存在: 可以以某种方式消除这个缺点吗?