gpt4 book ai didi

c++ - 如果包含 ,则 operator== 不会编译

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:27:35 25 4
gpt4 key购买 nike

如果满足以下条件,则以下代码可以完美编译:

  1. 我不包括 <iostream>或者

  2. 我叫 operator==作为alp::operator== .

我想 <iostream> 有问题和 operator== ,但我不知道是什么。

我使用 gcc 7.3.0、clang++-6.0 和 goldbolt 编译代码。总是同样的错误。

问题是编译器试图转换 operator== 的参数至 const_iterator , 但为什么? (我想编译器没有看到我的 operator== 版本,而是寻找其他版本)。

#include <vector>
#include <iostream> // comment and compile


namespace alp{

template <typename It_base>
struct Iterator {
using const_iterator = Iterator<typename It_base::const_iterator>;

operator const_iterator() { return const_iterator{}; }
};


template <typename It_base>
bool operator==(const Iterator<It_base>& x, const Iterator<It_base>& y)
{ return true;}

}// namespace

struct Func{
int& operator()(int& p) const {return p;}
};


template <typename It, typename View>
struct View_iterator_base{
using return_type = decltype(View{}(*It{}));

using const_iterator =
View_iterator_base<std::vector<int>::const_iterator, Func>;
};


using view_it =
alp::Iterator<View_iterator_base<std::vector<int>::iterator, Func>>;


int main()
{
view_it p{};
view_it z{};

bool x = operator==(z, p); // only compiles if you remove <iostream>
bool y = alp::operator==(z,p); // always compile
}

错误信息:

yy.cpp: In instantiation of ‘struct View_iterator_base<__gnu_cxx::__normal_iterator<const int*, std::vector<int> >, Func>’:

yy.cpp:9:73: required from ‘struct alp::Iterator<View_iterator_base<__gnu_cxx::__normal_iterator<const int*, std::vector<int> >, Func> >’

yy.cpp:44:29: required from here

yy.cpp:28:42: error: no match for call to ‘(Func) (const int&)’
using return_type = decltype(View{}(*It{}));
~~~~~~^~~~~~~
yy.cpp:22:10: note: candidate: int& Func::operator()(int&) const <near match>
int& operator()(int& p) const {return p;}
^~~~~~~~
yy.cpp:22:10: note: conversion of argument 1 would be ill-formed:
yy.cpp:28:42: error: binding reference of type ‘int&’ to ‘const int’ discards qualifiers
using return_type = decltype(View{}(*It{}));
~~~~~~^~~~~~~

最佳答案

我在这里做了一个更简单的测试用例:https://godbolt.org/z/QQonMG .

相关详情是:

  • A using类型别名不会实例化模板。例如:

    template<bool b>
    struct fail_if_true {
    static_assert(!b, "template parameter must be false");
    };

    using fail_if_used = fail_if_true<true>;

    不会导致编译时错误(如果不使用 fail_if_used)

  • ADL 还会检查模板参数类。在这种情况下,std::vector<int>::iterator__gnu_cxx::__normal_iterator<const int*, std::vector<int> >, Func> , 它有一个 std::vector<int>在它的模板中。所以,operator==将检查全局 namespace (始终),alp (因为 alp::Iteratoralp 中),__gnu_cxxstd .

  • 你的 View_iterator_base::const_iterator是无效的。 View_iterator_base::const_interator::result_type定义为 decltype(Func{}(*std::vector<int>::const_iterator{})) . std::vector<int>::const_iterator{}将是一个 vectors const 迭代器,所以 *std::vector<int>::const_iterator{}const int& . Func::operator()需要 int& ,所以这意味着表达式无效。但由于上述原因,如果不使用它不会导致编译时错误。这意味着您的转换运算符是无效类型。
  • 因为您没有将其定义为 explicit ,转换运算符(无效类型)将用于尝试将其与函数参数匹配(如果它们尚未匹配)。显然这最终会实例化无效类型,因此会抛出编译时错误。
  • 我的猜测是 iostream包括 string ,它定义了 std::operator==用于字符串。

这是一个没有 std 的例子命名空间:https://godbolt.org/z/-wlAmv

// Avoid including headers for testing without std::
template<class T> struct is_const { static constexpr const bool value = false; } template<class T> struct is_const<const T> { static constexpr const bool value = true; }

namespace with_another_equals {
struct T {};

bool operator==(const T&, const T&) {
return true;
}
}

namespace ns {
template<class T>
struct wrapper {
using invalid_wrapper = wrapper<typename T::invalid>;
operator invalid_wrapper() {}
};

template<class T>
bool operator==(const wrapper<T>&, const wrapper<T>&) {
return true;
}
}

template<class T>
struct with_invalid {
static_assert(!is_const<T>::value, "Invalid if const");
using invalid = with_invalid<const T>;
};

template<class T>
void test() {
using wrapped = ns::wrapper<with_invalid<T>>;
wrapped a;
wrapped b;
bool x = operator==(a, b);
bool y = ns::operator==(a, b);
}

template void test<int*>();

// Will compile if this line is commented out
template void test<with_another_equals::T>();

请注意,只需声明 operator const_iterator()应该实例化类型。但这不是因为它在模板中。我的猜测是它在被检查以显示它无法编译之前被优化了(它编译的地方因为它未被使用)(它甚至没有用 -Wall -pedantic 警告它没有返回语句在我的例子中)。

关于c++ - 如果包含 <iostream>,则 operator== 不会编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55344802/

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