Не удается присвоить оператору преобразования - C++

Я пытаюсь преобразовать класс A в строку как таковую:

#include <iostream>
#include <string>

class A {
public:
  std::string data_ = "hello world";

  A() {}

  operator std::string() const {
    return data_;
  }

  template <typename T>
  operator T() const {
    return data_;
  }
};

int main() {
  A();

  // This fails
  // std::string s;
  // s = A();

  std::string s = A(); // This works
  return 0;
}

Я пытаюсь решить ту часть, где s = A();. Он терпит неудачу во время компиляции, и компилятор сообщает мне, что нет оператора присваивания '=', который присваивает A строке.

Что интересно:

  • если вызывается его конструктор копирования (с std::string s = A();), включается «оператор преобразования», и он работает (но я хочу, чтобы s = A() также работал).
  • Также, если я удалю метод шаблона, s = A(); будет работать.

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

Какой компилятор вы используете? gcc и clang объясняют, что происходит (неоднозначная перегрузка)

M.M 27.10.2018 00:15

У меня работает, когда удаляю шаблон. wandbox.org/permlink/ThiX9mLrvGsb1XlT. М.М прав в том, что ваша программа неоднозначна.

smac89 27.10.2018 00:18

@ M.M примерил clang и gcc. Да, я понимаю, что это неоднозначно, но я действительно не знаю, когда оператор преобразования имеет приоритет над оператором присваивания.

chutsu 27.10.2018 00:24

@ smac89 Я уже упоминал во втором пункте, он работает, если вы удалите метод шаблона. Любопытно, почему поведение отличается, когда его вводят.

chutsu 27.10.2018 00:25

напишите свой шаблон как operator typename std::remove_all_extents<T>::type() const { - он скомпилируется

nikniknik2016 27.10.2018 00:29

@chutsu проблема в том, что существует множество перегрузок std::string::operator= и множество возможных пользовательских последовательностей преобразования; Например, string::operator=(string) <- A::operator string не предпочтительнее, чем std::operator=(char *) <- A::operator char *. Этого не возникает в других примерах, поскольку они не связаны с operator=.

M.M 27.10.2018 00:31
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
6
109
1

Ответы 1

Решение простое. Сделайте это явным, а не неявным преобразованием:

  template <typename T>
  explicit operator T() const {
    return data_;
  }

Преимущество в том, что теперь работают все четыре возможности:

  std::string s;
  s = A();

  std::string s2 = A(); // This works
  std::string s3 = std::string(A());
  std::string s4;
  s4 = std::string(A());

Можете ли вы объяснить, почему явное указание оператора решает проблему? Имеет ли этот новый оператор приоритет над существующей версией без шаблона?

smac89 27.10.2018 01:02

Этот результат эквивалентен полному удалению operator T(), потому что operator std::string уже присутствует в примере. Спрашивающий уже заметил: «Если я удалю шаблонный метод, s = A (); работает». Предположительно, задающий вопрос хочет решение, которое преобразует типы Другие, а не std::string()?

Lack 27.10.2018 01:03

@Lack - это не эквивалент полного удаления operator T(). Если у вас есть T, который может быть сконструирован из string, его все равно можно явно вызвать

463035818_is_not_a_number 27.10.2018 01:33

@ user463035818 Результат эквивалентен в этом примере. Все "четыре возможности", которые вы показываете, называются operator std::string; никто не вызывает explicit operator T. Если у вас есть пример, в котором оператор explicit делает что-то полезное, ваш ответ будет улучшен, если он будет показан.

Lack 27.10.2018 03:40

@ Отсутствие, это не мой ответ;). Во всяком случае, насколько я понимаю OP, они действительно хотят, чтобы вызвал operator std::string, и причина, по которой он не работал, заключалась в существовании operator T, что делает operator T явным, позволяет вам вызывать operator string неявно без двусмысленности

463035818_is_not_a_number 27.10.2018 19:57

Ой, перепутал числовые имена пользователей! Конечно. Я предполагаю, что OP не совсем ясно, как они на самом деле используют operator T.

Lack 27.10.2018 20:20

Другие вопросы по теме