默认构造函数中的歧义
Ambiguity in default constructor
我试图了解 C++11 中引入的构造函数的一些默认选项,所以我正在阅读一些 notes from Bjarne。
在此页面上,他是以下示例:
struct Z {
// ...
Z(long long); // can initialize with an long long
Z(long) = delete; // but not anything less
};
他指出 Z
可以用 long long
构造,但 也一样 。这个措辞对我来说有点不清楚。我假设 "anything less" 可能指代 space 少于 long long
的任何东西。
我在我的机器上测试了一些尺寸,发现 long long
需要 8 个字节,long double
需要 16 个字节,所以我假设用 long double
构造就可以了,并且会简单地截断小数部分并将其强制为 long long
.
我写了这个:
class Foo {
public:
Foo(long long x) : x(x) {}
Foo(long x) = delete;
private:
long long x;
};
int main() {
Foo foo1(100LL); // Compiles fine
// Foo foo2(100L); // Compile error - cannot construct with smaller than `long long`. This is obvious
Foo foo3(42.0L); // This causes an error
return 0;
}
令我惊讶的是,上面的代码导致了一个错误:
error: call of overloaded 'Foo(long double)' is ambiguous
Foo foo3(42.0L);
这对我来说似乎很明确。为什么编译器不能解决这个问题?
已删除的构造函数已声明,但未定义。而不是 undefined,而是 deleted。
当编译器进行函数重载决策时,它会使用已声明的兼容函数的集合,其中也包括已删除的函数。如果重载解析恰好 select 一个已删除的函数,那么你会得到一个编译器错误。如果重载决议无法决定最佳函数,您也会收到编译器错误,即使歧义来自已删除的函数。
您可能认为删除的函数不参与重载决议会更好。但这用处不大。如果不想Foo(long)
参与重载决议,就不写了!
这类似于 public/private 函数的重载。即使从 class 外部调用,public 和私有函数也参与重载决议:
class Foo
{
public:
void fun(long long);
private:
void fun(long);
};
int main()
{
Foo f;
f.fun(100LL); //ok
f.fun(100L); //error: fun(long) is private
f.fun(1.0); //error: call is ambiguous
}
我试图了解 C++11 中引入的构造函数的一些默认选项,所以我正在阅读一些 notes from Bjarne。
在此页面上,他是以下示例:
struct Z {
// ...
Z(long long); // can initialize with an long long
Z(long) = delete; // but not anything less
};
他指出 Z
可以用 long long
构造,但 也一样 。这个措辞对我来说有点不清楚。我假设 "anything less" 可能指代 space 少于 long long
的任何东西。
我在我的机器上测试了一些尺寸,发现 long long
需要 8 个字节,long double
需要 16 个字节,所以我假设用 long double
构造就可以了,并且会简单地截断小数部分并将其强制为 long long
.
我写了这个:
class Foo {
public:
Foo(long long x) : x(x) {}
Foo(long x) = delete;
private:
long long x;
};
int main() {
Foo foo1(100LL); // Compiles fine
// Foo foo2(100L); // Compile error - cannot construct with smaller than `long long`. This is obvious
Foo foo3(42.0L); // This causes an error
return 0;
}
令我惊讶的是,上面的代码导致了一个错误:
error: call of overloaded 'Foo(long double)' is ambiguous Foo foo3(42.0L);
这对我来说似乎很明确。为什么编译器不能解决这个问题?
已删除的构造函数已声明,但未定义。而不是 undefined,而是 deleted。
当编译器进行函数重载决策时,它会使用已声明的兼容函数的集合,其中也包括已删除的函数。如果重载解析恰好 select 一个已删除的函数,那么你会得到一个编译器错误。如果重载决议无法决定最佳函数,您也会收到编译器错误,即使歧义来自已删除的函数。
您可能认为删除的函数不参与重载决议会更好。但这用处不大。如果不想Foo(long)
参与重载决议,就不写了!
这类似于 public/private 函数的重载。即使从 class 外部调用,public 和私有函数也参与重载决议:
class Foo
{
public:
void fun(long long);
private:
void fun(long);
};
int main()
{
Foo f;
f.fun(100LL); //ok
f.fun(100L); //error: fun(long) is private
f.fun(1.0); //error: call is ambiguous
}