如果满足以下条件,则以下代码可完美编译:
我不包括<iostream>或
我命名operator==为alp::operator==。
我想有一个问题<iostream>和operator==,但我不知道是什么。
我用gcc 7.3.0,clang ++-6.0和goldbolt编译代码。总是相同的错误。
问题在于编译器正在尝试将to的参数转换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
}
Run Code Online (Sandbox Code Playgroud)
错误信息:
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{}));
~~~~~~^~~~~~~
Run Code Online (Sandbox Code Playgroud)
我在这里做了一个最小的测试用例:https : //godbolt.org/z/QQonMG。
相关详细信息是:
一个using类型别名并没有实例化一个模板。因此,例如:
template<bool b>
struct fail_if_true {
static_assert(!b, "template parameter must be false");
};
using fail_if_used = fail_if_true<true>;
Run Code Online (Sandbox Code Playgroud)
不会导致编译时错误(如果fail_if_used未使用)
ADL还检查模板参数类。在这种情况下,std::vector<int>::iteratoris 模板中__gnu_cxx::__normal_iterator<const int*, std::vector<int> >, Func>包含一个std::vector<int>。因此,operator==将检查在全局命名空间(总是), alp(由于alp::Iterator是alp),__gnu_cxx和std。
View_iterator_base::const_iterator无效。View_iterator_base::const_interator::result_type定义为decltype(Func{}(*std::vector<int>::const_iterator{}))。std::vector<int>::const_iterator{}将是向量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>();
Run Code Online (Sandbox Code Playgroud)
请注意,仅声明operator const_iterator()应实例化类型。但这不是因为它在模板中。我的猜测是,在对其进行检查以表明它无法编译(它甚至没有警告-Wall -pedantic说它在我的示例中没有return语句)之前,已经对其进行了优化(由于未使用,它会在哪里进行编译)。)。
| 归档时间: |
|
| 查看次数: |
227 次 |
| 最近记录: |