4

这是今天让我感到困惑的第二个编译器错误。不知何故,对于下面的代码,gcc 抱怨该代码具有返回迭代器return_iter返回冲突类型std::_Rb_tree_iterator<const int*>的函数std::_Rb_tree_const_iterator<const int*>,但它们都不应该是 const 迭代器,因为集合不是 const。谁能解释为什么在std::end()非 const 左值上调用该方法时返回 a const_iterator

完整的代码粘贴在下面。

注意我只在使用gcc. 当我用 clang ( 编译这个错误时没有出现这个错误Apple LLVM version 8.0.0 (clang-800.0.38)。我使用的 gcc 版本是g++ (GCC) 5.1.0

一个相关的问题。这是forward的正确用法吗?std::forward每当您想使用转发参考时都可以调用吗?我在下面调用它的原因是为了以防万一当对象是右值时类型重载了一些方法。


#include <vector>
#include <string>
#include <set>
#include <iostream>
using namespace std;

int global_value = 1;

class LessPtr {
public:

    template <typename PointerComparableOne, typename PointerComparableTwo>
    constexpr auto operator()(PointerComparableOne&& lhs,
                              PointerComparableTwo&& rhs) const {
        return *std::forward<PointerComparableOne>(lhs) <
            *std::forward<PointerComparableTwo>(rhs);
    }

    using is_transparent = std::less<void>::is_transparent;
};

template <typename Container, typename Key>
auto return_iter(Container&& container, Key&& key) {
    if (global_value == 1) {
        return std::forward<Container>(container).lower_bound(std::forward<Key>(key));
    }
    else {
        return std::end(std::forward<Container>(container));
    }
}

void do_stuff(std::set<const int*, LessPtr>& set_ptrs) {
    // auto value = string{"something"};
    auto value = 1;
    auto iter = return_iter(set_ptrs, &value);
    cout << reinterpret_cast<void*>(&iter) << endl;
}

int main() {
    std::set<const int*, LessPtr> set_ptrs;
    do_stuff(set_ptrs);

    return 0;
}

LessPtr某种方式需要导致此错误..

4

1 回答 1

5

std::set这是处理透明比较器的方式中的一个 libstdc++ 错误。这是一个较短的示例:

int main() {
    using S = std::set<const int*, LessPtr>;
    S set_ptrs;

    int i = 0;
    const int ci = 0;
    static_assert(std::is_same<
          decltype(set_ptrs.lower_bound(&ci)), S::iterator>{}, "!"); // OK
    static_assert(std::is_same<
          decltype(set_ptrs.lower_bound(&i)), S::iterator>{}, "!");  // Error

    return 0;
}

第一个断言很好,我们调用lower_bound(Key const&),它返回一个iterator。第二个断言触发是因为我们调用了函数 template template <class K> lower_bound(K const&),因为LessPtr它是透明的,并且重载是更好的匹配(因为它是精确匹配),而对于 libstdc++,它返回一个const_iterator.

set_ptrs不是const,所以不应该。我提交了 78134

于 2016-10-27T15:48:39.217 回答