防止 bool 中的隐式对象构造?
Prevent implict object construction from bool?
我有一个class、X
,它有以下构造函数:
class X{
X(int64_t, int16_t, bool, int8_t);
X(int64_t, int16_t, bool);
X(double);
X(double, FT);
explicit X(const string&);
X(const string&, Y);
};
问题是编译器曾经创建了一个只传递一个布尔值的 X 对象(假设它是允许这个的双构造函数?)并且它导致了一个问题。
为了防止这种情况,我将 bool 构造函数显式化并删除了它:
explicit X(bool) = delete;
但现在我收到编译器错误:
EXPECT_EQUALS(X("9.8901099"), a/b);
EXPECT_EQUALS(X{"56267"}, x);
X x{"-56267E-1"};
X b("5");
编译器说我使用了删除的函数explicit X(bool) = delete
如何防止从布尔创建 X 的对象?
发生这种情况是因为 bool
比 std::string
更适合 const char[]
。当你没有接受 bool
的 ctor 时,就会选择 std::string
一个。当你有一个带 bool
的构造函数时,就会选择这个重载。只是删除了所以调用是非法的
让我们用一个简单的自由重载函数看看这个行为:
auto foo(int) { cout << "foo int" << endl; }
auto foo(std::string const &) { cout << "foo string" << endl; }
auto main() -> int {
foo(3); // int
foo("Asdf"); // std::string
}
添加 bool
重载时:
auto foo(int) { cout << "foo int" << endl; }
auto foo(std::string const &) { cout << "foo string" << endl; }
auto foo(bool) { cout << "foo bool" << endl; }
auto main() -> int {
foo(3); // int
foo("Asdf"); // bool (also warning implicit conversion turn string literal into bool)
}
解决方法是添加一个char const *
重载:
auto foo(int) { cout << "foo int" << endl; }
auto foo(std::string const &) { cout << "foo string" << endl; }
auto foo(char const *s) {
cout << "foo char const *" << endl;
// possibly:
return foo(std::string{s});
}
auto foo(bool) = delete;
auto main() -> int {
foo(3); // int
foo("Asdf"); // char const *
foo(true); // error
}
因为一些遗留代码使用 returns char *
而不是 char const *
你可能还需要添加一个 char *
重载。
首先,您需要了解如果显式删除 bool 构造函数会发生什么。它在重载 selection 中变得可用,当它是最佳匹配时,它就会被使用,然后给出一个编译器错误,因为它被删除了。
这与您未定义它时不同,因为您确实可以 'stop' 通过隐式转换转换的布尔值加上后跟 class [的(不同的)构造函数=12=],因为它是布尔值的最佳匹配,所以隐式转换到此为止。
考虑您的 class
的用途
X x("abc");
没有删除的 bool
构造函数,这个 selects X(const string&)
.
然而,使用删除的 bool
构造函数,这将 select 和 explicit X(bool)
,后者也被删除,因此会产生编译器错误。正如 Kerrek SB 所说,解决这个问题的方法是也为 const char *
定义一个构造函数。
确实,如果您不删除 bool
构造函数,那么下面的 select 就是 double
X x(true);
首先转换为 int
,然后转换为 double
。
因此,您可以选择删除或不删除的解决方案,但您需要了解后果和要求。如果删除它,则需要提供一个 const char *
构造函数。如果您不删除它,那么您需要接受 bool
可用于构建 class.
的实例这一事实
我有一个class、X
,它有以下构造函数:
class X{
X(int64_t, int16_t, bool, int8_t);
X(int64_t, int16_t, bool);
X(double);
X(double, FT);
explicit X(const string&);
X(const string&, Y);
};
问题是编译器曾经创建了一个只传递一个布尔值的 X 对象(假设它是允许这个的双构造函数?)并且它导致了一个问题。
为了防止这种情况,我将 bool 构造函数显式化并删除了它:
explicit X(bool) = delete;
但现在我收到编译器错误:
EXPECT_EQUALS(X("9.8901099"), a/b);
EXPECT_EQUALS(X{"56267"}, x);
X x{"-56267E-1"};
X b("5");
编译器说我使用了删除的函数explicit X(bool) = delete
如何防止从布尔创建 X 的对象?
发生这种情况是因为 bool
比 std::string
更适合 const char[]
。当你没有接受 bool
的 ctor 时,就会选择 std::string
一个。当你有一个带 bool
的构造函数时,就会选择这个重载。只是删除了所以调用是非法的
让我们用一个简单的自由重载函数看看这个行为:
auto foo(int) { cout << "foo int" << endl; }
auto foo(std::string const &) { cout << "foo string" << endl; }
auto main() -> int {
foo(3); // int
foo("Asdf"); // std::string
}
添加 bool
重载时:
auto foo(int) { cout << "foo int" << endl; }
auto foo(std::string const &) { cout << "foo string" << endl; }
auto foo(bool) { cout << "foo bool" << endl; }
auto main() -> int {
foo(3); // int
foo("Asdf"); // bool (also warning implicit conversion turn string literal into bool)
}
解决方法是添加一个char const *
重载:
auto foo(int) { cout << "foo int" << endl; }
auto foo(std::string const &) { cout << "foo string" << endl; }
auto foo(char const *s) {
cout << "foo char const *" << endl;
// possibly:
return foo(std::string{s});
}
auto foo(bool) = delete;
auto main() -> int {
foo(3); // int
foo("Asdf"); // char const *
foo(true); // error
}
因为一些遗留代码使用 returns char *
而不是 char const *
你可能还需要添加一个 char *
重载。
首先,您需要了解如果显式删除 bool 构造函数会发生什么。它在重载 selection 中变得可用,当它是最佳匹配时,它就会被使用,然后给出一个编译器错误,因为它被删除了。
这与您未定义它时不同,因为您确实可以 'stop' 通过隐式转换转换的布尔值加上后跟 class [的(不同的)构造函数=12=],因为它是布尔值的最佳匹配,所以隐式转换到此为止。
考虑您的 class
的用途X x("abc");
没有删除的 bool
构造函数,这个 selects X(const string&)
.
然而,使用删除的 bool
构造函数,这将 select 和 explicit X(bool)
,后者也被删除,因此会产生编译器错误。正如 Kerrek SB 所说,解决这个问题的方法是也为 const char *
定义一个构造函数。
确实,如果您不删除 bool
构造函数,那么下面的 select 就是 double
X x(true);
首先转换为 int
,然后转换为 double
。
因此,您可以选择删除或不删除的解决方案,但您需要了解后果和要求。如果删除它,则需要提供一个 const char *
构造函数。如果您不删除它,那么您需要接受 bool
可用于构建 class.