Проблемный код C ++ 03:

#include <cstddef>
struct Foo {
    explicit Foo(const char *){}
    Foo &operator=(const char *) {return *this;}
    Foo &operator=(char) {return *this;}
};
int main() {
    Foo s("foobar");
    s = NULL;
}

Ошибка:

In file included from /opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/cstddef:50,
                 from <source>:1: <source>: In function 'int main()': <source>:9:9: error: ambiguous overload for 'operator=' (operand types are 'Foo' and 'long int')
    9 |     s = NULL;
      |         ^~~~ <source>:4:10: note: candidate: 'Foo& Foo::operator=(const char*)'
    4 |     Foo &operator=(const char *) {return *this;}
      |          ^~~~~~~~ <source>:5:10: note: candidate: 'Foo& Foo::operator=(char)'
    5 |     Foo &operator=(char) {return *this;}
      |          ^~~~~~~~

Если я правильно понимаю, источник проблемы заключается в том, что NULL в C ++ 03 может действовать как целое число и как указатель. Мне также известно, что C ++ 11 и более поздние версии предоставляют nullptr для решения этой проблемы. Обновление до C ++ 11 для меня не вариант.

Вопрос: как эта проблема решается на практике и как сохранить возможность давать перегрузки?

Один из способов - запретить пользователю использовать NULL. Есть программное решение?

1
Ave Milia 12 Фев 2021 в 07:47

1 ответ

Лучший ответ

Один из способов добиться этого - использовать прокси-структуру для char, что сделает operator=(const char*) предпочтительным. Так:

#include <cstddef>

struct MyChar
{
    MyChar(char c) : c(c){}
    operator char() {return c;}
    char c;
};

struct Foo {
    explicit Foo(const char *){}
    Foo &operator=(const char *) {return *this;}
    Foo &operator=(MyChar) {return *this;}
};
int main() {
    Foo s("foobar");
    s = NULL;
    s = 'x';
    s = "foo";
}
3
Eugene 12 Фев 2021 в 05:07