gpt4 book ai didi

c++ - 通过推导实现一个map_keys_iterator : a single compiler error

转载 作者:太空宇宙 更新时间:2023-11-04 12:23:34 25 4
gpt4 key购买 nike

我在周末再次使用 C++ 并开始注意到一些我不确定它从何而来的东西。

Following the advice in this thread , 我决定实现 map_keys_iteratormap_values_iterator .我采用了——我认为——推荐的反对方法,从 std::map<K,V>::iterator 派生一个类。并这样实现:

template <typename K, typename V>
struct map_values_iterator:
public std::map<K,V>::iterator {
// explicitly call base's constructor
typedef typename std::map<K,V>::iterator mIterator;
map_values_iterator (const mIterator& mi) :
mIterator(mi) {};

const V& operator* () const { return (*this)->second; }
};

到目前为止,一切顺利,并且以下代码有效(nvm Unicode,我默认使用支持 i18n 的终端):

typedef std::map<double,string> Map;
Map constants;
constants[M_PI] = "π";
constants[(1+sqrt(5))/2] = "φ";
constants[exp(M_PI)-M_PI] = "fake_20";
// ... fill map with more constants!
map_values_iterator<double, std::string> vs(constants.begin());
for (; vs != m.end(); ++vs) {
cout<< (vs != m.begin() ? ", " : "")<< *vs;
}
cout<< endl;

此代码打印出预期的结果,类似于(因为 Map 的元素是有序的):

..., φ, ..., π, ...., fake_20, ....

所以我猜 map_keys_iterator也会以类似的方式工作。我注意 map 的 value_type 实际上是 pair<const K, V>所以 keys 版本将返回一个值。

但是,必须声明迭代器的类型很笨重,所以我想用经典的 make_pair 创建一个调用程序- 像成语。这就是麻烦开始的地方:

template <typename K, typename V>
map_values_iterator<K,V> map_values(const typename std::map<K,V>::iterator &i) {
return lpp::map_values_iterator<K,V> (i);
}

template <typename K, typename V>
map_values_iterator<K,V> map_values(const typename std::map<K,V>::const_iterator &i) {
return lpp::map_values_iterator<K,V> (i);
}

我相对确定此函数具有正确的签名和构造函数调用。但是,如果我尝试从代码中调用该函数:

auto vs= map_values(constants.begin());

我收到一个形式为 STL 编译器的错误:

error: no matching function for call to ‘map_values(std::_Rb_tree_iterator<std::pair<const double, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >)’

我在这里假设在这个特殊情况下整个 _Rb_tree_iterator实际上是 map::iterator 的正确迭代器类型定义;但是我不完全确定。我尝试提供更多重载以查看其中一个是否匹配(删除引用、删除 const、仅使用非 const_iterator 变体等),但到目前为止,没有任何东西允许我感兴趣的签名。

如果我在调用函数之前将基本迭代器存储在一个变量中(如 auto begin= constans.begin(); auto vs= map_values(begin); 中),我会得到完全相同的基本错误,只是不匹配调用的描述明显不同(因为它是一个“const blah& ").

我第一次尝试实现这种迭代器是通过创建一个聚合了 map::iterator 的基类。而不是继承和派生两个类,每个类都有足够的 operator* , 但那个版本遇到了比上面更多的问题,仍然迫使我复制太多的界面。所以我尝试了这个选项来进行代码探索。

我试图寻找这个问题的答案,但我的 Google-fu 今天不是很强大。也许我遗漏了一些明显的东西,也许我忘记了推导的东西(尽管我几乎可以肯定我没有——迭代器与容器不同),也许我实际上需要为 map 指定所有模板参数,或者也许我的编译器坏了,但无论它是什么,我都找不到它,而且我很难理解编译器在这里提示的实际是什么。根据我以前的经验,如果您对 STL 做错了什么,您应该会看到大量错误,而不仅仅是一个(这不是要启动的 STL)。

所以...任何(封装良好的)指针将不胜感激。

最佳答案

原因是你的KV类型参数处于不可推导的上下文中,因此您的函数模板甚至在重载解析期间都不会被实例化。

再看一遍:

template <typename K, typename V>
map_keys_iterator<K,V> map_keys(const typename std::map<K,V>::iterator &i)

为此,C++ 编译器必须以某种方式从特定的 iterator 开始。类为其“父容器”类型 - map在这种情况下 - 得到它的 KV .一般来说,这是不可能的 - 毕竟,一个特定的 iterator可能是某个其他类的 typedef,调用中参数的实际类型是那个其他类;编译器无法“追溯”它。因此,根据 C++ 标准,在这种情况下它甚至不会尝试 - 更一般地说,在您有 typename SomeType<T>::OtherType 的任何情况下, 和 T是一个类型参数。

你可以做的是让整个参数类型成为模板类型参数。这需要一些技巧才能得出 KV , 不过。

template <typename Iterator>
map_keys_iterator<
typename std::iterator_traits<Iterator>::value_type::first_type,
typename std::iterator_traits<Iterator>::value_type::second_type
> map_keys(Iterator i)

不幸的是,在调用您的类型的构造函数时,您还必须在函数体中重复这两个。

附带说明一下,迭代器通常按值传递(它们本来就是轻量级的)。

关于c++ - 通过推导实现一个map_keys_iterator : a single compiler error,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3645199/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com