std :: set迭代器的冲突返回类型

时间:2016-10-27 15:17:35

标签: c++ c++11 gcc auto const-iterator

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

完整的代码粘贴在下面。

注意我在使用gcc进行编译时只会出现此错误。使用clang(Apple LLVM version 8.0.0 (clang-800.0.38)进行编译时,此错误不会显示。我使用的gcc版本为g++ (GCC) 5.1.0

相关问题。这是正确使用前进吗?只要您想使用转发引用,是否可以调用std::forward?我在下面调用它的原因只是在类型为对象是rvalue时重载某些方法的情况。

#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以某种方式需要导致此错误..

1 个答案:

答案 0 :(得分: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 <class K> lower_bound(K const&),因为LessPtr是透明的,并且该重载是一个更好的匹配(因为它是一个完全匹配),而对于libstdc ++,这个是返回const_iterator

set_ptrs不是const,所以它不应该是 "secretFunction(secretElement.setSecretAttribute('<button class=\"button-default\">MyButton</button>'));"; 。我提交了78134