没有从int到自定义类的可行转换

No viable conversion from int for custom class

本文关键字:转换 自定义 int      更新时间:2023-10-16

我编写了一个UTF8字符类,使用以下方法:

typedef uint32_t CodePoint; // This is meant to represent any unicode character
explicit Char(const char c);
explicit Char(const CodePoint cp);
Char& operator=(const char c);
Char& operator=(const CodePoint cp);

但是当我试图通过传递一个数字来构造一个新类时,我得到了一个错误:

utf8::Char c = 0x20AC; // No viable conversion from int to utf8::Char
utf8::Char c(0x20AC);  // Call to constructor of 'utf8::Char' is ambiguous

为什么我看到这些错误?

typedef uint32_t CodePoint; // This is meant to represent any unicode character

你意识到c++ 11为这个目的定义了一个不同的char32_t类型吗?

utf8::Char c = 0x20AC; // No viable conversion from int to utf8::Char

这不是赋值,它是构造。这种语法称为复制初始化,相当于:

utf8::Char c = utf8::Char(0x20AC);

除了从intutf8::Char的转换是隐式的,因此不能使用explicit构造函数。

utf8::Char c(0x20AC); // Call to constructor of 'utf8::Char' is ambiguous

intchar的转换并不比从intuint32_t的转换更好或更差。

是否有一种方法可以说"使用CodePoint构造函数除了char"。

是的,在c++类型系统中表示"一切"的通常方式是模板:

explicit Char(char c);
template<typename T>
  explicit Char(T cp);

当实参为char时,首选Char(char)构造函数(因为重载解析更倾向于选择非模板而不是模板,否则它们会有歧义),对于其他所有内容,将使用构造函数模板。

因为您不希望模板构造函数接受所有类型,所以如果使用非整型调用它,您可能希望使其出错。在c++ 11中,你可以这样做:

template<typename T>
  explicit Char(T cp)
  {
    static_assert(std::is_integral<T>::value, "utf8::Char should only be constructed from integral types");
  }

0x20AC是数字,所以必须提供另一个重载构造函数。