C++ 不像 Java 那样进行类型擦除。要创建异构容器(这是您尝试做的技术术语),您需要广泛使用 std::any 或 std::variant,它们是 C++17 引入的新类。
std::vector<std::any> values{1.0, "Hello", -42, 'b'};
for(auto & any : values) {
int * i;
if(val = std::any_cast<int>(&any)) std::cout << "int: " << *i << std::endl;
const char ** s;
if(s = std::any_cast<const char *>(&any)) std::cout << "string-literal: " << *s << std::endl;
double * d;
if(d = std::any_cast<double>(&any)) std::cout << "double: " << *d << std::endl;
char * c;
if(c = std::any_cast<char>(&any)) std::cout << "char: " << *c << std::endl;
}
请注意该代码有多么混乱。尤其是因为许多人希望将"hello" 存储为std::string 对象,但除非用户明确指定它,否则这是无法做到的:
std::vector<std::any> values{1.0, std::string{"Hello"}, -42, 'b'};
无论如何,我个人的意见是使用std::variant 会更合适,因为您可以更清楚地了解容器的使用方式,并且可以避免与std::any:
typedef std::variant<std::string, char, double, int> my_variant;
struct visitor {
void operator()(std::string const& v) const {
std::cout << "std::string: " << v<< std::endl;
}
void operator()(double const& v) const {
std::cout << "double: " << v << std::endl;
}
void operator()(int const& v) const {
std::cout << "int: " << v << std::endl;
}
void operator()(char const& v) const {
std::cout << "char: " << v << std::endl;
}
};
int main() {
std::vector<my_variant> values{1.0, "Hello", -42, 'b'};
for(my_variant & variant : values) {
std::visit(visitor{}, variant);
}
return 0;
}
如果我们不需要知道类型,我们甚至可以使用auto lambdas 使变体版本更简单:
typedef std::variant<std::string, char, double, int> my_variant;
int main() {
std::vector<my_variant> values{1.0, "Hello", -42, 'b'};
for(my_variant & variant : values) {
std::visit(
[](auto const& val) {std::cout << "Some unknown type: " << val << std::endl;},
variant
);
}
return 0;
}
我没有通过我的编译器运行它,但这应该可以很好地了解如何在 C++ 中完成此类任务。
如果您无法访问 C++17,则可以使用 boost.any 和 boost.variant,我有理由确定它们都是标头-only 库,因此很容易导入到您的项目中。