My std::variant
có thể để trống (std::monostate
), chứa int
, std::string
hoặc bool
.Tại sao biến thể của tôi chuyển đổi chuỗi std :: thành bool?
Khi tôi muốn cho nó ăn bằng một chuỗi, được cho là var = "this is my string"
, nó được chuyển đổi thành bool
và không thành chuỗi. Nếu tôi khai báo kiểu rõ ràng, nó hoạt động var = std::string("this is my string")
. Tại sao vậy và có điều gì tôi có thể làm để tránh nó?
#include <string>
#include <variant>
#include <iostream>
int main()
{
using var = std::variant<std::monostate, int, std::string, bool>;
var contains_nothing;
var contains_int = 5;
var contains_string = "hello";
var contains_expl_string = std::string("explicit hello");
var contains_bool = false;
auto visitor = [](auto&& arg){
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same<T, std::monostate>())
std::cout<<"nothing\n";
else if constexpr (std::is_same<T, int>())
std::cout<<"int: "<<arg<<"\n";
else if constexpr (std::is_same<T, std::string>())
std::cout<<"string: "<<arg<<"\n";
else if constexpr (std::is_same<T, bool>())
std::cout<<"bool: "<<arg<<"\n";
else
std::cout<<"Visitor is not exhaustive\n";
};
std::visit(visitor, contains_nothing); // nothing
std::visit(visitor, contains_int); // int: 5
std::visit(visitor, contains_string); // bool: 1
std::visit(visitor, contains_expl_string); // string: explicit hello
std::visit(visitor, contains_bool); // bool: 0
}
EDIT Vì người dùng của mã của tôi có thể không thực hiện một cách rõ ràng string
s, tôi muốn hiểu được. Nếu không, nó sẽ là một nguồn lỗi. Tôi đã thực hiện chức năng trợ giúp mẫu để kiểm tra nếu một char*
đã được thông qua và nếu như vậy, làm cho một chuỗi :: std. Hoạt động tốt. Trợ giúp để làm cho điều này đơn giản hơn được đánh giá cao!
EDIT 2 Bằng cách khai báo std::monostate
như tham số default/loại, nó thậm chí còn hoạt động khi make_var
được gọi mà không cần bất kỳ cuộc tranh cãi.
#include <string>
#include <variant>
#include <iostream>
using var = std::variant<std::monostate, int, std::string, bool>;
template<typename T = std::monostate>
var make_var(T value = std::monostate())
{
if constexpr (std::is_same<typename std::remove_const<typename std::decay<T>::type>::type, const char*>())
return std::string(value);
return value;
}
int main()
{
auto contains_nothing = make_var();
auto contains_int = make_var(3);
auto contains_string = make_var("hello");
auto contains_expl_string = make_var(std::string("excplicit hello"));
var contains_bool = make_var(false);
auto visitor = [](auto&& arg){
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same<T, std::monostate>())
std::cout<<"nothing\n";
else if constexpr (std::is_same<T, int>())
std::cout<<"int: "<<arg<<"\n";
else if constexpr (std::is_same<T, std::string>())
std::cout<<"string: "<<arg<<"\n";
else if constexpr (std::is_same<T, bool>())
std::cout<<"bool: "<<arg<<"\n";
else
std::cout<<"Visitor is not exhaustive\n";
};
std::visit(visitor, contains_nothing);
std::visit(visitor, contains_int);
std::visit(visitor, contains_string);
std::visit(visitor, contains_expl_string);
std::visit(visitor, contains_bool);
}
Một câu hỏi để hỏi là, tại sao nên 'std :: chuỗi' được ưa thích để 'bool'? Cả hai yêu cầu phân rã mảng và chuyển đổi loại. – juanchopanza
Xem câu trả lời đáng yêu của tôi cho http://stackoverflow.com/questions/44021989/implicit-cast-from-const-string-to-bool đặc biệt là cách giải quyết của tôi bằng cách sử dụng mẫu ;-). Nhưng Angew sử dụng một người dùng được xác định bằng chữ (bên dưới) thì dễ thương hơn. – Bathsheba
câu trả lời ngắn: nó không, bởi vì đó không phải là một 'std :: string' bạn đã cho nó. –