运行时确定C++的类型

Tim*_*Tim 5 c++ types runtime

我想知道是否可以将类型确定为C++中的运行时信息.

(1)虽然我的问题很笼统,但为简单起见,我将从一个简单的例子开始:

 #include <stdio.h>  
 #include <iostream>  
 #include <cstring>  
 using namespace std;  
 int main(int argc, char * argv[])  
 {  
 if (strcmp(argv[1], "int")==0)   
 {  
     int t = 2;   
 }else if (strcmp(argv[1], "float")==0)  
 {  
     float t = 2.2; 
 } 
 cout << t << endl;  // error: ‘t’ was not declared in this scope
 return 0;  
 }
Run Code Online (Sandbox Code Playgroud)

对于此示例,有两个问题:

(a)"argv [1] to t"是错误的,但C字符串argv [1]中的类型信息是否可以转换为实际的类型关键字?所以我们不需要通过if-else子句和strcmp检查每种类型.

(b)如何在if子句的局部范围内定义的变量t仍在外部有效.即如何将局部变量"导出"到其范围之外?

(2)一般来说,不是特定于上面的简单示例,运行时确定类型的常用方法是什么?在我看来,可能有一些方法:

(a)可以将类型定义的变量的处理放在同一范围内定义.例如

 #include <stdio.h>  
 #include <iostream>  
 #include <cstring>  
 using namespace std;  
 int main(int argc, char * argv[])  
 {  
 if (strcmp(argv[1], "int")==0)   
 {  
     int t = 2;   
     cout << t << endl; 
 }else if (strcmp(argv[1], "float")==0)  
 {  
     float t = 2.2; 
     cout << t << endl; 
 } 
 return 0;  
 }
Run Code Online (Sandbox Code Playgroud)

并且可能使用模板函数使各种类型的公共代码可重用.

(b)或者可以使用抽象类类型和多态来间接导出定义,但我不确定如何.

谢谢你的建议!

小智 8

1a:不,类型不是C++中的对象或值(例如,在Python中).但是,您可以使用由argv [1]的值选择的各种值.

1b:对不起,就是不能那样做.

2:dynamic_cast和typeid(两个运算符)是当前由查询类型的语言提供的唯一工具(并不罕见,大多数语言都有很少但专用的工具),并且通常不鼓励使用它们来查询类型关于情况(在其他语言中也不常见).

2a:是的,因为这是简单的,显而易见的,并且在这里工作 - 没有理由使用其他任何东西,但是因为它是示例代码,我们假设您需要一个不同的解决方案.您可以调用在正确类型上实例化的函数模板,但由于这与2a的其余部分几乎相同,所以我不会进入它.

2b:使用子类模板的示例,因为它很方便:

struct Base {
  virtual ~Base() {}
  friend std::ostream& operator<<(std::ostream& s, Base const& v) {
    v._print(s);
    return s;
  }
private:
  virtual void _print(std::ostream&) const = 0;
};

template<class T>
struct Value : Base {
  T data;
  explicit
  Value(T const& data) : data(data) {}
private:
  virtual void _print(std::ostream& s) const {
    s << data;
  }
};
Run Code Online (Sandbox Code Playgroud)

使用:

int main(int argc, char** argv) {
  using namespace std;
  auto_ptr<Base> p;
  string const type = argc > 1 ? argv[1] : "int";
  if (type == "int") {
    p.reset(new Value<int>(2));
  }
  else if (type == "float") {
    p.reset(new Value<double>(2.2));
  }
  cout << *p << '\n';
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

这开始将两种类型合并为一种类型,它们在这里都呈现相同的接口Base.然而,这并不适用于每个解决方案,并且诸如boost.variant之类的变体可以更好,特别是当所需的各种类型数量少且事先已知时.


Han*_*ant 5

您需要一个能够存储不同类型值的类.如果没有工会,Boost的变体类将是正确的选择.