提问人:Horus 提问时间:8/22/2023 更新时间:8/22/2023 访问量:63
变体中从基元类型到用户定义类型的隐式转换
Implicit conversion from primitive to user-defined types in variant
问:
我有两个类和 hat 模仿各自的基元类型,应该在 .几乎可以编译的示例:Int
Bool
std::variant
#include <iostream>
#include <string>
#include <variant>
using namespace std;
class Bool {
public:
Bool(bool val) : m_value(val) {}
operator bool() const { return m_value; }
private:
bool m_value{false};
};
class Int {
public:
Int(int val) : m_value(val) {}
operator int() const { return m_value; }
private:
int m_value{0};
};
int main() {
using VariantT = std::variant<std::string, Bool, Int>;
Bool b1 = true;
VariantT v1 = b1; // (1) works
VariantT v2 = true; // (2) does not work
VariantT v3 = 1; // (3) does not work
return 0;
}
如果我从 VariantT 中删除,(3) 可以工作。删除可使 (1) 和 (2) 正常工作。Bool
Int
但是当 和 存在时,没有一个有效:Int
Bool
test.cpp:32:12: error: no viable conversion from 'bool' to 'VariantT' (aka 'variant<basic_string<char>, Bool, Int>')
VariantT v2 = true; // (2) does not work
^ ~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/variant:1365:7: note: candidate constructor not viable: no known conversion from 'bool' to 'const variant<basic_string<char>, Bool, Int> &' for 1st argument
variant(const variant& __rhs) = default;
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/variant:1366:7: note: candidate constructor not viable: no known conversion from 'bool' to 'variant<basic_string<char>, Bool, Int> &&' for 1st argument
variant(variant&&) = default;
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/variant:1378:2: note: candidate template ignored: requirement '18446744073709551615UL < sizeof...(_Types)' was not satisfied [with _Tp = bool, $1 = enable_if_t<sizeof...(_Types) != 0>, $2 = enable_if_t<__not_in_place_tag<bool>>]
variant(_Tp&& __t)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/variant:1388:2: note: explicit constructor is not a candidate
variant(in_place_type_t<_Tp>, _Args&&... __args)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/variant:1408:2: note: explicit constructor is not a candidate
variant(in_place_index_t<_Np>, _Args&&... __args)
(将 Clang++ 16 与 C++17 一起使用)
我希望能够将基元类型分配给 并将它们隐式转换为 或 .VariantT
Int
Bool
为什么它不起作用?我怎样才能让它工作?
谢谢!
答:
3赞
Sam Varshavchik
8/22/2023
#1
例如,在 C++ 中,如果函数参数是 ,则可以传入一个值,并进行隐式转换。反之亦然。这会导致一个问题:int
bool
VariantT v2 = true; // (2) does not work
这里有两种可能的、不同的隐式转换。
使用带有参数的构造函数来构造 ,然后使用 .
Bool
true
Bool
Bool
使用 的构造函数,将 传递转换为 int 值 1 的构造函数,以构造一个 ,然后用 构造 。
Int
true
Int
Int
这两种转换都比另一种转换更可取,因此过载解析会因此而失败。
我怎样才能让它工作?
改变一些东西。重新设计一些东西,做一些事情来禁用隐式转换。一种方法是弄乱构造函数,以防止它们接受隐式转换,并强制它们严格接受相应的类型:
#include <type_traits>
// ...
template<typename T, typename=std::enable_if_t<std::is_same_v<T, bool>>>
Bool(const T &val) : m_value(val) {}
// ...
template<typename T, typename=std::enable_if_t<std::is_same_v<T, int>>>
Int(const T &val) : m_value(val) {}
现在,的构造函数无法解析重载,除非它的参数是实数的、骨架的,而 的构造函数无法重载解析,除非它的参数是实数的、骨架的。Bool
bool
Int
int
请注意,这还可以防止 s、s 和其他整数挤过。一种可能的变化是,您可能想尝试一下。char
long
!std::is_same_v<T,bool>
评论