Ich versuche, einen generischen umgekehrten Wrapper für Container zu schreiben, die bidirektionale Iteratoren mit std::reverse_iterator
verwenden.Warum geht die Bereichsauflösung nicht außerhalb der Klasse?
Allerdings scheint es, dass, wenn der Compiler für begin(...)
oder end(...)
aussieht, es wird sagen, dass es keinen passenden Funktionsaufruf reverse_wrapper<CONTAINER>::begin(container)
weil der Kandidat 0 Argumente finden erwartet, aber 1 zur Verfügung gestellt.
Ich hätte gedacht, das ist, weil std::begin(myArray&)
und std::end(myArray&)
nicht existieren. Sie in den Namespace std
zu zwingen, funktionierte nicht (und ist sowieso nicht ratsam). Ich habe auch versucht, die std::
Präfixe von meinem reverse_wrapper
zu entfernen, aber das hat nicht funktioniert und würde auch die funktionierende std
Containerimplementierung brechen.
Dies scheint ein Problem Bereich Auflösung zu sein, aber ich kann nicht scheinen, um die Lösung zu bekommen. Was mache ich falsch?
Code:
#include <iterator>
#include <iostream>
#include <vector>
#define Fn1 0 // std container WORKS
#define Fn2 1 // non-std container DOESN'T WORK
template <typename Container>
struct reverse_wrapper
{
Container& container;
auto begin()
-> std::reverse_iterator< decltype(std::end(container)) >
{
return std::reverse_iterator< decltype(std::end(container)) >(std::end(container));
}
auto end()
-> std::reverse_iterator< decltype(std::begin(container)) >
{
return std::reverse_iterator< decltype(std::begin(container)) >(std::begin(container));
}
};
template <typename Container>
auto reverse(Container&& container)
-> reverse_wrapper<Container>
{
return{ container };
}
struct myArray
{
int elements[5] = {1,2,3,4,5};
};
int* begin(myArray& array) { return &array.elements[0]; }
int* end(myArray& array) { return &array.elements[5]; }
#if Fn1
void fn1()
{
std::vector<int> x = { 1,2,3,4,5 };
for (auto& ix : reverse(x))
{
std::cout << ix << std::endl;
}
std::cout << "-----" << std::endl;
for (auto& ix : x)
{
std::cout << ix << std::endl;
}
}
#endif
#if Fn2
void fn2()
{
myArray x;
for (auto& ix : reverse(x))
{
std::cout << ix << std::endl;
}
std::cout << "-----" << std::endl;
for (auto& ix : x)
{
std::cout << ix << std::endl;
}
}
#endif
int main()
{
#if Fn1
fn1();
#endif
#if Fn2
fn2();
#endif
}
Fehler:
In instantiation of 'struct reverse_wrapper': 61:30: required from here 14:56: error: no matching function for call to 'end(myArray&)' 14:56: note: candidates are: In file included from /usr/include/c++/4.9/string:51:0, from /usr/include/c++/4.9/bits/locale_classes.h:40, from /usr/include/c++/4.9/bits/ios_base.h:41, from /usr/include/c++/4.9/ios:42, from /usr/include/c++/4.9/ostream:38, from /usr/include/c++/4.9/iterator:64, from 1: /usr/include/c++/4.9/bits/range_access.h:68:5: note: template decltype (__cont.end()) std::end(_Container&) end(_Container& __cont) -> decltype(__cont.end()) ^ /usr/include/c++/4.9/bits/range_access.h:68:5: note: template argument deduction/substitution failed: /usr/include/c++/4.9/bits/range_access.h: In substitution of 'template decltype (__cont.end()) std::end(_Container&) [with _Container = myArray]': 14:56: required from 'struct reverse_wrapper' 61:30: required from here /usr/include/c++/4.9/bits/range_access.h:68:5: error: 'struct myArray' has no member named 'end' In instantiation of 'struct reverse_wrapper': 61:30: required from here /usr/include/c++/4.9/bits/range_access.h:78:5: note: template decltype (__cont.end()) std::end(const _Container&) end(const _Container& __cont) -> decltype(__cont.end()) ^ /usr/include/c++/4.9/bits/range_access.h:78:5: note: template argument deduction/substitution failed: /usr/include/c++/4.9/bits/range_access.h: In substitution of 'template decltype (__cont.end()) std::end(const _Container&) [with _Container = myArray]': 14:56: required from 'struct reverse_wrapper' 61:30: required from here /usr/include/c++/4.9/bits/range_access.h:78:5: error: 'const struct myArray' has no member named 'end' In instantiation of 'struct reverse_wrapper': 61:30: required from here /usr/include/c++/4.9/bits/range_access.h:97:5: note: template _Tp* std::end(_Tp (&)[_Nm]) end(_Tp (&__arr)[_Nm]) ^ /usr/include/c++/4.9/bits/range_access.h:97:5: note: template argument deduction/substitution failed: 14:56: note: mismatched types '_Tp [_Nm]' and 'myArray' In file included from /usr/include/c++/4.9/bits/basic_string.h:42:0, from /usr/include/c++/4.9/string:52, from /usr/include/c++/4.9/bits/locale_classes.h:40, from /usr/include/c++/4.9/bits/ios_base.h:41, from /usr/include/c++/4.9/ios:42, from /usr/include/c++/4.9/ostream:38, from /usr/include/c++/4.9/iterator:64, from 1: /usr/include/c++/4.9/initializer_list:99:5: note: template constexpr const _Tp* std::end(std::initializer_list) end(initializer_list __ils) noexcept ^ /usr/include/c++/4.9/initializer_list:99:5: note: template argument deduction/substitution failed: 14:56: note: 'myArray' is not derived from 'std::initializer_list' 20:58: error: no matching function for call to 'begin(myArray&)' 20:58: note: candidates are: In file included from /usr/include/c++/4.9/string:51:0, from /usr/include/c++/4.9/bits/locale_classes.h:40, from /usr/include/c++/4.9/bits/ios_base.h:41, from /usr/include/c++/4.9/ios:42, from /usr/include/c++/4.9/ostream:38, from /usr/include/c++/4.9/iterator:64, from 1: /usr/include/c++/4.9/bits/range_access.h:48:5: note: template decltype (__cont.begin()) std::begin(_Container&) begin(_Container& __cont) -> decltype(__cont.begin()) ^ /usr/include/c++/4.9/bits/range_access.h:48:5: note: template argument deduction/substitution failed: /usr/include/c++/4.9/bits/range_access.h: In substitution of 'template decltype (__cont.begin()) std::begin(_Container&) [with _Container = myArray]': 20:58: required from 'struct reverse_wrapper' 61:30: required from here /usr/include/c++/4.9/bits/range_access.h:48:5: error: 'struct myArray' has no member named 'begin' In instantiation of 'struct reverse_wrapper': 61:30: required from here /usr/include/c++/4.9/bits/range_access.h:58:5: note: template decltype (__cont.begin()) std::begin(const _Container&) begin(const _Container& __cont) -> decltype(__cont.begin()) ^ /usr/include/c++/4.9/bits/range_access.h:58:5: note: template argument deduction/substitution failed: /usr/include/c++/4.9/bits/range_access.h: In substitution of 'template decltype (__cont.begin()) std::begin(const _Container&) [with _Container = myArray]': 20:58: required from 'struct reverse_wrapper' 61:30: required from here /usr/include/c++/4.9/bits/range_access.h:58:5: error: 'const struct myArray' has no member named 'begin' In instantiation of 'struct reverse_wrapper': 61:30: required from here /usr/include/c++/4.9/bits/range_access.h:87:5: note: template _Tp* std::begin(_Tp (&)[_Nm]) begin(_Tp (&__arr)[_Nm]) ^ /usr/include/c++/4.9/bits/range_access.h:87:5: note: template argument deduction/substitution failed: 20:58: note: mismatched types '_Tp [_Nm]' and 'myArray' In file included from /usr/include/c++/4.9/bits/basic_string.h:42:0, from /usr/include/c++/4.9/string:52, from /usr/include/c++/4.9/bits/locale_classes.h:40, from /usr/include/c++/4.9/bits/ios_base.h:41, from /usr/include/c++/4.9/ios:42, from /usr/include/c++/4.9/ostream:38, from /usr/include/c++/4.9/iterator:64, from 1: /usr/include/c++/4.9/initializer_list:89:5: note: template constexpr const _Tp* std::begin(std::initializer_list) begin(initializer_list __ils) noexcept ^ /usr/include/c++/4.9/initializer_list:89:5: note: template argument deduction/substitution failed: 20:58: note: 'myArray' is not derived from 'std::initializer_list' In function 'void fn2()': 61:30: error: invalid initialization of reference of type 'myArray&' from expression of type 'reverse_wrapper' 38:6: note: in passing argument 1 of 'int* begin(myArray&)' 61:30: error: invalid initialization of reference of type 'myArray&' from expression of type 'reverse_wrapper' 39:8: note: in passing argument 1 of 'int* end(myArray&)'
Entfernen Sie die 'std ::' in 'std :: begin' und' std :: end', fügen Sie dann 'using std :: begin; Verwenden Sie std :: end' an den Stellen, an denen Sie 'begin' und' end' verwenden. Es könnte besser sein, automatisch abgeleiteten Typ anstelle von nachgestellten Rückgabetyp in einigen Fällen zu verwenden – KABoissonneault
@KABoissonneault, yeah, ich habe gedacht, mit einem 'using std :: begin/end ', aber es wird nicht im Klassenbereich so funktionieren Der Rückgabetyp kann es nicht finden. Ich dachte auch an einen automatisch abgeleiteten Typ, aber das funktioniert nicht in VS2013. – Adrian
Wie wäre es, sie im Namensraumbereich zu verwenden? – KABoissonneault