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

How to know whether std::iterator_traits<T>::value_type is defined

本文关键字:何知道 gt value type lt 是否 定义 std iterator traits      更新时间:2023-10-16

可能的重复项:
enable_if迭代器作为默认模板参数?

我正在寻找解决方案,以便在编译时知道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++标准和标准库标准,并且独立于编译器。

这个问题可以用评论中的方法显示出来:

#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编译器的结果为:01

由此可见,这还不足以解决问题。还是我做错了什么?

解决方案是这样的,但缺点是自定义迭代器类必须在类内部定义 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;
}

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