首页 \ 问答 \ 有没有办法确保在C ++中传递的模板参数是一个迭代器?(Is there a way of ensuring the template argument passed in C++ is an iterator?)

有没有办法确保在C ++中传递的模板参数是一个迭代器?(Is there a way of ensuring the template argument passed in C++ is an iterator?)

在C ++中,我正在实现vector类,并在使用任何类型作为T的参数时遇到错误:

void insert(iterator where, size_type count, const_reference value = T()){...}

template <typename InIt>
void insert(iterator where, InIt first, InIt last){...}

在执行以下操作时:

vector<int> v;
for (int i = 0; i < 5; ++i)
{
    v.push_back(i + 1);
}
v.insert(v.begin() + 2, 10, 8);
v.insert(v.begin() + 4, 9);

它将InIt的参数作为int ,它实际上应该是一个iterator类型的类,并且意味着调用了错误的函数,导致内部内存错误。 因此,我不得不使用template <typename InIt>参数来移除insert函数,因为它破坏了我的实现。 我已经试过这与std::string并发生同样的问题。

我能做些什么来区分这两个功能?


In C++, I am making an implementation of the vector class and came across an error when using any type as the argument for T:

void insert(iterator where, size_type count, const_reference value = T()){...}

template <typename InIt>
void insert(iterator where, InIt first, InIt last){...}

When doing the following:

vector<int> v;
for (int i = 0; i < 5; ++i)
{
    v.push_back(i + 1);
}
v.insert(v.begin() + 2, 10, 8);
v.insert(v.begin() + 4, 9);

It takes the argument for InIt as int, when it should in fact be an iterator type class and means that the wrong function is called, resulting in internal memory errors. As a result, I have had to remove the insert function with the template <typename InIt> argument as it ruins my implementation. I have tried this with std::string and the same problem occurs.

Is there anything I can do to differentiate these two functions?


原文:https://stackoverflow.com/questions/31123289
更新时间:2019-09-10 23:17

最满意答案

这就是SFINAE的用途 - 如果InIt不是看起来像迭代器的东西,那么从重载集合中删除第二个重载。 在这种情况下,您只需要一个输入迭代器,它必须既可以递增又可以取消引用:

template <typename InIt,
          typename = decltype(*std::declval<InIt&>(),
                              ++std::declval<InIt&>())>
void insert(iterator where, InIt first, InIt last)
{
    ...
}

如果你想用一些整型来调用insert (这样它可以转换为size_t ), *std::declval<InIt&>将是一个无效的表达式,因为整型不可忽略 - 所以模板扣除将失败。 因为我们不会考虑这个超载,所以我们不会考虑这个超载,而是第一个被调用。


This is what SFINAE is for - remove the 2nd overload from the overload set if InIt is not something that looks like an iterator. In this case, you just want an input iterator, which has to be both incrementable and dereferencable:

template <typename InIt,
          typename = decltype(*std::declval<InIt&>(),
                              ++std::declval<InIt&>())>
void insert(iterator where, InIt first, InIt last)
{
    ...
}

If you were to call insert with some integral type (so that it can be converted to size_t), *std::declval<InIt&> would be an invalid expression since integral types aren't dereferencable - so template deduction would fail. Because Substitution Failure Is Not An Error, the effect is that this overload is removed from consideration, and the first one would be called instead.

2015-06-29

相关问答

更多

函数作为模板参数传递(Function passed as template argument)

是的,它是有效的。 至于使其与乐手一起工作,通常的解决方案是这样的: template <typename F> void doOperation(F f) { int temp=0; f(temp); std::cout << "Result is " << temp << std::endl; } 现在可以称之为: doOperation(add2); doOperation(add3()); 这样做的问题是,如果编译器对add2的调用进行内联操作非常棘手,因为所有的编译器都知 ...

C ++模板构造函数(C++ template constructor)

调用构造函数模板时,没有办法明确指定模板参数,因此必须通过参数推导来推导出模板参数。 这是因为如果你说: Foo<int> f = Foo<int>(); <int>是Foo类型的模板参数列表,而不是其构造函数。 构造函数模板的参数列表无处可去。 即使您的解决方法,您仍然必须传递一个参数才能调用该构造函数模板。 这并不清楚你想要实现的目标。 There is no way to explicitly specify the template arguments when calling a c

C ++模板特化朋友迭代器错误:无效使用不完整类型(C++ template specialisation friend iterator error: invalid use of incomplete type)

错误消息非常清楚。 当您尝试在以下函数中创建类的实例时, class DoublyLinkedListIterator<double>是不完整的类型: iterator begin() { return iterator(this); } iterator end(){ return iterator(count); } 您可以使用以下任一方法解决此问题。 在template<typename T> class DoublyLi

常量参数的模板参数推导(template argument deduction for const argument)

为什么T推导为int而不是const int,为什么我应该修改一个函数? 因为你正在传递价值和接受价值(而不是参考)。 根据语言语法,这种推导总是会导致优先于non-const over const 。 为了更好地理解,请在C ++ 11代码下面尝试打印typeid : const int a = 5; // `a` typeid is `const int` auto b = a; // `b` typeid is `int` 扣除在这种情况下如何工作? 如果您希望a是不可修改的,并

如何创建一个返回传递的参数名称的函数(How to make a function that returns the name of the argument passed)

C ++不是正确的语言,它根本没有反射功能,你不能对待“任何东西,类,函数,变量等”。 均匀。 您不能将类传递给函数,或将函数传递给函数,它们不是对象。 C++ is not the right language to do this, it has no reflection capabilities at all, and you can't treat "anything, class, function, variable etc." uniformly. You can't pass

C ++任何具有特定值类型的迭代器?(C++ any iterator with a specific value type?)

您可以通过std :: iterator_traits获取迭代器的value_type ,然后在编译时检查它,例如 template<class iter_type> void f(iter_type start, iter_type finish) { static_assert( std::is_same< typename std::iterator_traits<iter_type>::value_type, specific_value ...

模板模板参数的部分实例化(Partial instantiation of template template parameter)

不可以。 模板模板参数不能与函数模板一起使用。 模板模板参数的模板参数必须是id-expression,用于命名类模板或模板别名。 No. Template template arguments can't be used with function template. A template argument for a template template parameter must be an id-expression which names a class template or a t

带有默认参数的C ++模板模板参数(C++ template template parameter with default parameters)

问题是你的模板模板参数只有两个模板参数,而不是map ,它有四个。 template<class Key, template<class, class, class, class> class Map = std::map> class MyClass { }; 要么 template<class Key, template<class...> class Map = std::map> class MyClass { }; 应该编译 。 但是,要避免此类问题,请尝试改为使用地图类型,并通过相 ...

相关文章

更多

最新问答

更多
  • .net Rx:消息的有序批处理(.net Rx: in-order batch-processing of messages)
  • 查询在给定区域中包含全景图的商业场所的api?(Query places api for business venues in given area which contain panoramas?)
  • linux启动的时候的两条进度条各表示在加载什么?
  • 测试是否已存在某些内容(Testing if something already exists)
  • iOS7和jQuery mobile:面板在打开和关闭后变为空白(iOS7 and jQuery mobile: panel goes blank once opened and closed)
  • 在Spring中结合GET和POST请求方法(Combine GET and POST request methods in Spring)
  • 从Geany内部运行应用程序的多个实例(Run multiple instances of an application from inside Geany)
  • 使用Yii2在邮件中嵌入图像时出错(Error when embed image in mail using Yii2)
  • 带有不同频率的LED计数器程序(0 - 15)(Led Counter Program (0 - 15) with different frequencies)
  • Google支持SAML 2.0 ECP(Google support for SAML 2.0 ECP)
  • 如何识别结构构件的尺寸?(How can i identify the size of structure member?)
  • 带有计数器的列表迭代中的Netlogo列表(Netlogo list in list iterations with counter)
  • Eclipse CDT中对函数的未定义引用(undefined reference to function in Eclipse CDT)
  • 如何确定一个类是否是java中接口的实现(How to determine if a class which is an implemenation of an interface in java)
  • Wireshark捕获过滤器示例(Wireshark Capture Filter Example)
  • 什么是NoSQL?(What exactly is NoSQL?)
  • 如何在sass中编写媒体查询?(How to write media queries in sass?)
  • spring destroy-method +请求范围bean(spring destroy-method + request scope bean)
  • ssis包中全局表的范围(Scope of Global Table in ssis package)
  • 如何在较小的屏幕上禁用Bootstrap的“词缀”?(How can I disable Bootstrap's “affix” on smaller screens?)
  • SQLite Min函数在使用String数据的行中返回NULL(SQLite Min function returns NULL in row with String data)
  • 如何在Cordova中更新应用程序版本(How to update app version in Cordova)
  • 当我在while循环中使用char []读取Android中的文本文件时出现重复行(repeated lines when I use char[] in while loop for reading text file in Android)
  • 有没有办法按顺序打印数组,在[TCL]中输入条目(Is there a way to print array in order with entries entered in that [TCL])
  • 如何在倒排索引结构中搜索短语查询?(How to search phrase queries in inverted index structure?)
  • 导致在WCF中返回HTTP错误状态(Causing HTTP error status to be returned in WCF)
  • qsqltablemodel不兼容的数据类型(qsqltablemodel incompatible data types)
  • 如何在没有包的情况下引用Java文件?(How can I reference Java files without packages?)
  • Rails 4.1.1相关模型属性,嵌套表单不保存(Rails 4.1.1 related model attribute with nested form not saving)
  • 如何将byte []转换成字符串?(How to convert UTF-8 byte[] to string?)