我正在寻找解决方案,以便在编译时知道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库标准和独立于编译器。
答案 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;
}
现在的问题仍然存在: 可以以某种方式消除这个缺点吗?