видимость оператора шаблона, gcc vs clang

У меня есть этот код, опираясь на выражение сгиба, вызывающее очень общий оператор сравнения:

#include <type_traits>
#include <vector>
#include <list>

template <typename Iter_a, typename Iter_b>
auto operator<(Iter_a, Iter_b) {
// original code makes more sense, I assure you
if constexpr  ( std::is_same_v<Iter_a, Iter_b> ) {
return Iter_a();
}
else return Iter_b();
}

template <typename... Iterators>
using weakest_iterator = std::decay_t<decltype( (Iterators() < ...) )>;

int main() {
using lit = std::list<int>::iterator;
using vit = std::vector<int>::iterator;
using wi = weakest_iterator<lit, vit, float*>;
}

У меня есть две проблемы с этим кодом:

Во-первых, g ++ компилирует его и clang ++ (-std=gnu++2a) отказывается это сделать:

prog.cc:14:64: error: call to function 'operator<' that is neither visible in the template definition nor found by argument-dependent lookup
using weakest_iterator = std::decay_t<decltype( (Iterators() < ...) )>;
^
prog.cc:19:16: note: in instantiation of template type alias 'weakest_iterator' requested here
using wi = weakest_iterator<lit, vit, float*>;
^
prog.cc:6:6: note: 'operator<' should be declared prior to the call site
auto operator<(Iter_a, Iter_b) {

У тебя есть идеи почему? Меня особенно беспокоит то, что clang запрашивает определение до места вызова в строке 19, которое он находит самостоятельно в строке 6.

Во-вторых, если я изменю его, чтобы вызвать мою мета-функцию с аргументами шаблона указателя (using wi = weakest_iterator<int*, float*, float*>;, Я получаю еще одно сообщение об ошибке, на этот раз только с g ++, так как clang отказывается компилировать, что мне трудно понять:

main.cpp: In substitution of 'template<class ... Iterators> using weakest_iterator = std::decay_t<decltype ((Iterators() < ...))> [with Iterators = {int*, float*, float*}]':

main.cpp:19:57:   required from here

main.cpp:14:75: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]

using weakest_iterator = std::decay_t<decltype( (Iterators() < ...) )>;

Похоже, 1) встроенная перегрузка operator< называется (если есть что-то подобное) над моим универсальным, и 2) что сравнение int* и float* считается таким же, как сравнение указателя и целого числа.

Можно ли убедиться, что моя собственная реализация operator< выбирается компилятором?

3

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]