Хитрый оператор преобразования типа
От: Videoman Россия https://hts.tv/
Дата: 29.06.22 10:43
Оценка:
Есть код. Это просто минимизация на которой видна проблема:
#include <type_traits>

template<typename type_t>
inline constexpr bool is_bool_v = std::is_same_v<std::remove_cv_t<type_t>, bool>;

struct A
{
    template<typename type_t, std::enable_if_t<is_bool_v<type_t>, int> = 0>
    operator type_t() const;
    template<typename type_t>
    type_t get() const;
};

template<typename type_t, std::enable_if_t<is_bool_v<type_t>, int>>
inline A::operator type_t() const
{
    return type_t();
}

template<typename type_t>
type_t A::get() const
{
    return A::operator type_t();
}

int main()
{
    A a;

    const bool b = a.get<bool>();

    return 0;
}

Допустим у класса 'A' нужно реализовать метод get(), который сам вызывает оператор преобразования типа. clang и gcc без проблем компилируют этот код, но msvc выдает ошибку: 'error C3861: 'operator bool': identifier not found'
Не пойму в чём проблема, кто прав и что делать?
Re: Хитрый оператор преобразования типа
От: σ  
Дата: 29.06.22 11:17
Оценка: 4 (1)
V>Это просто минимизация на которой видна проблема

Просто минимизация на которой видна проблема выглядит так:
struct A
{
    template<typename T>
    operator T();

    template<typename T>
    T get() { return A::operator T(); }
};

int main()
{
    A{}.get<bool>();
}
а не то, что у тебя.

V>что делать?


Прекратить выпендриваться и заменить A:: на this->

V>кто прав?


Почитай стандарт, думаю, там найдётся ответ.
Отредактировано 29.06.2022 11:20 σ . Предыдущая версия .
Re[2]: Хитрый оператор преобразования типа
От: Videoman Россия https://hts.tv/
Дата: 29.06.22 11:39
Оценка:
Здравствуйте, σ, Вы писали:

σ>Просто минимизация на которой видна проблема выглядит так:

σ>
struct A
σ>{
σ>    template<typename T>
σ>    operator T();

σ>    template<typename T>
σ>    T get() { return A::operator T(); }
σ>};

σ>int main()
σ>{
σ>    A{}.get<bool>();
σ>}
а не то, что у тебя.

Да, действительно. Просто минимизация понятие относительное и всегда боишься убрать лишнее.

σ>Прекратить выпендриваться и заменить A:: на this->

И в чем тут выпендривание, объясни?
Действительно, с this работает. Спасибо большое. Иногда получаешь проблему в таком неожиданном месте, что забываешь потыкать палочкой.

σ>Почитай стандарт, думаю, там найдётся ответ.

Да, так всё просто ?! Может тогда поможешь и укажешь точно на параграф?
Re[3]: Хитрый оператор преобразования типа
От: σ  
Дата: 29.06.22 11:58
Оценка:
V>Да, действительно. Просто минимизация понятие относительное и всегда боишься убрать лишнее.
Да не, минимизация — понятие вполне строгое.
Процесс, на выходе которого получается код, из которого нельзя убрать конструкций так, чтобы не сломать воспроизведение проблемы.
Ну максимум что-то для читабельности можно оставить, чтобы минимизация не превратилась в обфускацию.

σ>>Прекратить выпендриваться и заменить A:: на this->

V>И в чем тут выпендривание, объясни?
Да я просто так написал.

V>Действительно, с this работает. Спасибо большое. Иногда получаешь проблему в таком неожиданном месте, что забываешь потыкать палочкой.

Вообще вроде и без this-> должно, но не работает.

σ>>Почитай стандарт, думаю, там найдётся ответ.

V>Да, так всё просто ?!
А ты думал.

V>Может тогда поможешь и укажешь точно на параграф?

Если время будет. Хотя смотреть в новые лукап-правила смысла может не иметь, они всё ещё слишком новые.
Re[4]: Хитрый оператор преобразования типа
От: Videoman Россия https://hts.tv/
Дата: 29.06.22 12:51
Оценка:
Здравствуйте, σ, Вы писали:

σ>Да не, минимизация — понятие вполне строгое.

Ок. Признаю, что оставил лишние детали, которые, как мне казалось, влияют на проблему.

σ>Вообще вроде и без this-> должно, но не работает.

Понятно, что ничего не понятно. Всю дорогу думал, что при отсутствии наследования и виртуальности метода, выражения эквивалентны:

// вызов минуя таблицу виртуальных функций (ломается на MSVC)

A::method(); 
this->A::method();
(*this).A::method();

// вызываем через таблицу виртуальных функций (если есть).
method(); 
this->method();
(*this).method();
В любом случае проблема решена и на этом спасибо. Может кто-нибудь еще потом объяснит в чем тут засада.
Re[3]: Хитрый оператор преобразования типа
От: rg45 СССР  
Дата: 29.06.22 12:53
Оценка: 4 (1)
Здравствуйте, Videoman, Вы писали:

V>Да, так всё просто ?! Может тогда поможешь и укажешь точно на параграф?


А я вот заморочился и поискал. И вот, что нашел:

1) https://timsong-cpp.github.io/cppwp/n4618/temp.mem#5

A specialization of a conversion function template is referenced in the same way as a non-template conversion function that converts to the same type.


2) (Сразу вслед за первым) https://timsong-cpp.github.io/cppwp/n4618/temp.mem#6

A specialization of a conversion function template is not found by name lookup. Instead, any conversion function templates visible in the context of the use are considered. For each such operator, if argument deduction succeeds ([temp.deduct.conv]), the resulting specialization is used as if found by name lookup.


Выходит, что работать должен и твой вариант, и даже без "A::", а просто: "return operator type_t()". Похоже, msvc просто не может разрулить между conversion function и conversion function template.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: Хитрый оператор преобразования типа
От: rg45 СССР  
Дата: 29.06.22 13:06
Оценка: :))
Здравствуйте, Videoman, Вы писали:

V>Допустим у класса 'A' нужно реализовать метод get(), который сам вызывает оператор преобразования типа. clang и gcc без проблем компилируют этот код, но msvc выдает ошибку: 'error C3861: 'operator bool': identifier not found'

V>Не пойму в чём проблема, кто прав и что делать?

Забавные ошибки выдает msvc, однако:

struct A
{
   template <typename T>
   operator T();

   bool get() {
      return operator bool(); // error C2352: 'A::operator T': a call of a non-static member function requires an object
   }
};


То есть, он понимает, что 'A::operator T' — это нестатическая функция-член, но вот для какого она объекта вызвана — это загадка "со звездочкой"
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: Хитрый оператор преобразования типа
От: Videoman Россия https://hts.tv/
Дата: 29.06.22 13:21
Оценка:
Здравствуйте, rg45, Вы писали:

R>...

R>Выходит, что работать должен и твой вариант, и даже без "A::", а просто: "return operator type_t()". Похоже, msvc просто не может разрулить между conversion function и conversion function template.

Похоже ты прав и gcc и clang с тобой согласны.
Сейчас просто активно начал портировать код, что бы он работал одновременно и на Linux и на Windows, при том, что изначально код писался под Windows. Периодически наступаю на такие косяки, то с одной, то с другой стороны. Что интересно, MS в большинстве случаев работает в более расслабленном стиле, сам до всего догадывается и многое прощает, но видимо от этого и глючит в противоречивых, с точки зрения стандарта, случаях.
Отредактировано 29.06.2022 13:22 Videoman . Предыдущая версия .
Re[5]: Хитрый оператор преобразования типа
От: rg45 СССР  
Дата: 29.06.22 13:23
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Сейчас просто активно начал портировать код, что бы он работал одновременно и на Linux и на Windows, при том, что изначально код писался под Windows. Периодически наступаю на такие косяки, то с одной, то с другой стороны. Что интересно, MS в большинстве случаев работает в более расслабленном стиле, сам до всего догадывается и многое прощает, но видимо от этого и глючит в неопределённых, с точки зрения стандарта, случаях.


Ну, тут ничего нового, к этому всегда нужно быть готовым
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: Хитрый оператор преобразования типа
От: σ  
Дата: 29.06.22 13:56
Оценка: 12 (1)
R>А я вот заморочился и поискал. И вот, что нашел:
R>Выходит, что работать должен и твой вариант, и даже без "A::", а просто: "return operator type_t()".

Только вот это справедливо если ищется operator X, где X это конкретный тип.
Т.к. в `return operator type_t()`, даже с зависимым type_t, `operator type_t` это не dependent name, то должен [был] искаться, как я понимаю, литералли `operator type_t` (для какого-нибудь `struct type_t`) в template definition context. (https://cplusplus.github.io/CWG/issues/1500.html, https://godbolt.org/z/vjj3fGhzG)

Это было пофикшено в https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1787r6.html#temp.res
Отредактировано 29.06.2022 14:01 σ . Предыдущая версия . Еще …
Отредактировано 29.06.2022 14:00 σ . Предыдущая версия .
Re[5]: Хитрый оператор преобразования типа
От: rg45 СССР  
Дата: 29.06.22 14:22
Оценка:
Здравствуйте, σ, Вы писали:

σ>Только вот это справедливо если ищется operator X, где X это конкретный тип.

σ>Т.к. в `return operator type_t()`, даже с зависимым type_t, `operator type_t` это не dependent name, то должен [был] искаться, как я понимаю, литералли `operator type_t` (для какого-нибудь `struct type_t`) в template definition context. (https://cplusplus.github.io/CWG/issues/1500.html, https://godbolt.org/z/vjj3fGhzG)

А разве согласно (1.3) 'operator type_t' не является зависимым именем?

P.S. Как, вообще, такое может быть — 'type_t' я вляется зависимым, а 'operator type_t' — нет?
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 29.06.2022 14:26 rg45 . Предыдущая версия .
Re[6]: Хитрый оператор преобразования типа
От: σ  
Дата: 29.06.22 14:26
Оценка:
R>А разве согласно (1.3) 'operator type_t' не является зависимым именем?

Посмотри в грамматику template-id
Отредактировано 29.06.2022 14:26 σ . Предыдущая версия .
Re[7]: Хитрый оператор преобразования типа
От: rg45 СССР  
Дата: 29.06.22 14:31
Оценка:
Здравствуйте, σ, Вы писали:

R>>А разве согласно (1.3) 'operator type_t' не является зависимым именем?


σ>Посмотри в грамматику template-id


По здравому смыслу, это должно бы соответствовать operator-function-id, хотя, я вижу, что в списке операторов подходящего варианта для conversion function нет
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[8]: Хитрый оператор преобразования типа
От: σ  
Дата: 29.06.22 14:37
Оценка:
R>>>А разве согласно (1.3) 'operator type_t' не является зависимым именем?

σ>>Посмотри в грамматику template-id


R>По здравому смыслу, это должно бы соответствовать operator-function-id, хотя, я вижу, что в списке операторов подходящего варианта для conversion function нет


operator T это conversion-function-id = `operator` conversion-type-id, оно вообще не может быть template-id, в смысле конструкция "conversion-function-id < template-argument-list[opt] >" невозможна, "< template-argument-list[opt] >" ушло бы в conversion-type-id
Отредактировано 29.06.2022 14:40 σ . Предыдущая версия .
Re[9]: Хитрый оператор преобразования типа
От: rg45 СССР  
Дата: 29.06.22 14:48
Оценка:
Здравствуйте, σ, Вы писали:

σ>operator T это conversion-function-id = `operator` conversion-type-id, оно вообще не может быть template-id, в смысле конструкция "conversion-function-id < template-argument-list[opt] >" невозможна, "< template-argument-list[opt] >" ушло бы в conversion-type-id


Да, я понимаю, возразить мне нечего. В то же время, то, что конструкция 'operator T' не является зависимой от 'T', не укладывается у меня в голове. То ли это упущение, то ли это закопано где-то в пластах формулировок, х.з.

P.S. Блин, че-то я тормознул, ты же ссылку дал на фикс, только сейчас обратил внимание. Т.е. dependent, все-таки. Спасибо.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 29.06.2022 16:37 rg45 . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.