Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ STL容器迭代器的模板专门化?_C++_Templates_C++11_Stl_Iterator - Fatal编程技术网

C++ STL容器迭代器的模板专门化?

C++ STL容器迭代器的模板专门化?,c++,templates,c++11,stl,iterator,C++,Templates,C++11,Stl,Iterator,我正在尝试编写一个类似于std::to_string的模板函数,该函数适用于STL容器的基本类型和迭代器。但我不知道如何编写足够具体的模板,以便只识别迭代器 到目前为止,我尝试在STL容器中使用迭代器typedef template<typename... Args, template <typename...> class Container> static string to_string(typename Container<Args...>::

我正在尝试编写一个类似于std::to_string的模板函数,该函数适用于STL容器的基本类型和迭代器。但我不知道如何编写足够具体的模板,以便只识别迭代器

到目前为止,我尝试在STL容器中使用
迭代器
typedef

  template<typename... Args, template <typename...> class Container>
  static string to_string(typename Container<Args...>::iterator s) { ...
输出:

basic, Hello, basic
期望输出:

basic, Hello, itor

应该是这样的:

template<typename ForwardIterator>
static string to_string(ForwardIterator begin, ForwardIterator end) {
    return "itor ";
}
模板
静态字符串到_字符串(ForwardIterator开始,ForwardIterator结束){
返回“itor”;
}

如果只关心参数的迭代器性,而不关心容器的类型,那么可以忽略其他重载

首先生成一个
is\u迭代器
trait,如所示:

模板
结构sfinae_true:std::true_type{};
结构是迭代器测试仪{
模板
静态sfinae_真实测试(int);
模板
静态标准:假_型试验(…);
};
模板
struct is_iterator:decltype(is_iterator_tester::test(0)){};
现在,根据类型是否为迭代器,找到错误的重载:

//base case
template<typename T>
static std::enable_if_t<!is_iterator<T>::value, string> to_string(const T& t) {
  return "basic ";
}

//specialization for string
template <typename Char, typename Traits, typename Alloc>
static string to_string(const std::basic_string<Char, Traits, Alloc>& s) {
  return (string)s;
}

//Problem line: how to write specialization for iterators of standard containers?
template<typename T>
static std::enable_if_t<is_iterator<T>::value, string> to_string(const T& s) {
  return "itor ";
}
//基本情况
模板
静态标准::如果值,字符串>到字符串,则启用字符串(常量t&t){
返回“基本”;
}
//字符串专用化
模板
静态字符串到字符串(const std::basic_string&s){
返回(字符串)s;
}
//问题线:如何为标准容器的迭代器编写专门化?
模板
静态标准::启用字符串(常量t&s){
返回“itor”;
}

.

如果您将特定于迭代器的重载约束为使用定义了
运算符*
的任何类型(),那么这非常简单:

名称空间我的{
//基本情况
使用std::to_字符串;
//字符串重载
模板
基本字符串
to_字符串(标准::基本_字符串){
返回s;
}
//迭代器的重载
模板
自动到_字符串(迭代器i)->decltype(到_字符串(*i)){
返回“迭代器到:\”“+到字符串(*i)+'”;
}
}

左侧的
是一个非推断上下文。而且,这通常是不可能的。如果两个容器都使用一个原始指针作为迭代器呢?使用两个参数的字符串?那有点counterintuitive@MooingDuck:由于使用单个迭代器所能做的就是取消对它的引用,因此使用单个迭代器的to_字符串对我来说似乎毫无意义。
to_string(it)
to_string(*it)
的优点是什么?也许我误解了OP的问题,但听起来好像重点是字符串化容器。@另一方面,大多数只使用一个迭代器的函数要么毫无意义,要么是错误的。@JohnZwinck:我在OP中没有看到关于字符串化容器的内容,但另一方面,我想不出任何其他可能的用途,所以我想两个迭代器是有意义的。谢谢。我看到您的演示使用了
-std=c++1y
。我在gcc-4.8.1中尝试了这一点,但它没有编译,说
错误:“如果命名空间“std”中的“t”没有命名类型,则启用\u”。这是否需要gcc4.9?@TingL将
std::enable_if_t
替换为
typename std::enable_if::type
,如果编译器不支持它。谢谢,您的解决方案使用enable_if_t=typename std::enable_if::type与
模板一起工作谢谢。这简化了事情。请注意,如果传递的类型不能传递给
std::to_string
,但又不是迭代器或字符串,则不会编译。另外,
to_string('a')
将为您提供97,因为
std::to_string
没有比
int
更小的重载。这取决于用例,可能重要,也可能不重要。
template <typename T>
struct sfinae_true : std::true_type {};

struct is_iterator_tester {
    template <typename T>
    static sfinae_true<typename std::iterator_traits<T>::iterator_category> test(int);

    template <typename>
    static std::false_type test(...);
};

template <typename T>
struct is_iterator : decltype(is_iterator_tester::test<T>(0)) {};
//base case
template<typename T>
static std::enable_if_t<!is_iterator<T>::value, string> to_string(const T& t) {
  return "basic ";
}

//specialization for string
template <typename Char, typename Traits, typename Alloc>
static string to_string(const std::basic_string<Char, Traits, Alloc>& s) {
  return (string)s;
}

//Problem line: how to write specialization for iterators of standard containers?
template<typename T>
static std::enable_if_t<is_iterator<T>::value, string> to_string(const T& s) {
  return "itor ";
}
namespace My {
    // base case
    using std::to_string;

    // overload for strings
    template <typename Char, typename Traits, typename Alloc>
    std::basic_string<Char, Traits, Alloc>
    to_string(std::basic_string<Char, Traits, Alloc> s) {
        return s;
    }

    // overload for iterators
    template<typename Iterator>
    auto to_string(Iterator i) -> decltype(to_string(*i)) {
        return "iterator to: \"" + to_string(*i) + '"';
    }
}