热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如果包含<iostream>,则无法编译operator==

如何解决《如果包含<iostream>,则无法编译operator==》经验,为你挑选了1个好方法。

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

    我不包括

    我命名operator==alp::operator==

我想有一个问题operator==,但我不知道是什么。

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

问题在于编译器正在尝试将to的参数转换operator==const_iterator,但是为什么呢?(我想编译器看不到我的版本,而是在operator==寻找其他版本)。

#include 
#include  // comment and compile


namespace alp{

template 
struct Iterator {
    using const_iterator    = Iterator;

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


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

}// namespace

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


template 
struct View_iterator_base{
    using return_type     = decltype(View{}(*It{})); 

    using const_iterator =
              View_iterator_base::const_iterator, Func>;
};


using view_it =
    alp::Iterator::iterator, Func>>;


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

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

错误信息:

yy.cpp: In instantiation of ‘struct View_iterator_base<__gnu_cxx::__normal_iterator >, Func>’:

yy.cpp:9:73:   required from ‘struct    alp::Iterator >, 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 
 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{}));
                                ~~~~~~^~~~~~~

Artyer.. 5

我在这里做了一个最小的测试用例:https : //godbolt.org/z/QQonMG。

相关详细信息是:

一个using类型别名并没有实例化一个模板。因此,例如:

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

using fail_if_used = fail_if_true;

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

ADL还检查模板参数类。在这种情况下,std::vector::iteratoris 模板中__gnu_cxx::__normal_iterator >, Func>包含一个std::vector。因此,operator==将检查在全局命名空间(总是), alp(由于alp::Iteratoralp),__gnu_cxxstd

View_iterator_base::const_iterator无效。View_iterator_base::const_interator::result_type定义为decltype(Func{}(*std::vector::const_iterator{}))std::vector::const_iterator{}将是向量const迭代器,*std::vector::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 struct is_const { static constexpr const bool value = false; } template struct is_const { static constexpr const bool value = true; }

namespace with_another_equals {
    struct T {};

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

namespace ns {
    template
    struct wrapper {
        using invalid_wrapper = wrapper;
        operator invalid_wrapper() {}
    };

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

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

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

template void test();

// Will compile if this line is commented out
template void test();

请注意,仅声明operator const_iterator()应实例化类型。但这不是因为它在模板中。我的猜测是,在对其进行检查以表明它无法编译(它甚至没有警告-Wall -pedantic说它在我的示例中没有return语句)之前,已经对其进行了优化(由于未使用,它会在哪里进行编译)。)。



1> Artyer..:

我在这里做了一个最小的测试用例:https : //godbolt.org/z/QQonMG。

相关详细信息是:

一个using类型别名并没有实例化一个模板。因此,例如:

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

using fail_if_used = fail_if_true;

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

ADL还检查模板参数类。在这种情况下,std::vector::iteratoris 模板中__gnu_cxx::__normal_iterator >, Func>包含一个std::vector。因此,operator==将检查在全局命名空间(总是), alp(由于alp::Iteratoralp),__gnu_cxxstd

View_iterator_base::const_iterator无效。View_iterator_base::const_interator::result_type定义为decltype(Func{}(*std::vector::const_iterator{}))std::vector::const_iterator{}将是向量const迭代器,*std::vector::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 struct is_const { static constexpr const bool value = false; } template struct is_const { static constexpr const bool value = true; }

namespace with_another_equals {
    struct T {};

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

namespace ns {
    template
    struct wrapper {
        using invalid_wrapper = wrapper;
        operator invalid_wrapper() {}
    };

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

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

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

template void test();

// Will compile if this line is commented out
template void test();

请注意,仅声明operator const_iterator()应实例化类型。但这不是因为它在模板中。我的猜测是,在对其进行检查以表明它无法编译(它甚至没有警告-Wall -pedantic说它在我的示例中没有return语句)之前,已经对其进行了优化(由于未使用,它会在哪里进行编译)。)。


推荐阅读
author-avatar
潇洒看不惯_185
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有