有没有一种方法可以将类型说明符存储在变量中?

时间:2019-07-07 09:02:56

标签: c++ type-conversion decltype typeid

是否可以在变量中存储类型说明符?我到处搜索并找到typeid和decltype,但是它们都不如我所愿。 decltype不会生成变量,而typeid通常用于typeid()。name()。

由于typeid()。name()将类型说明符输出为const char *,可以将其存储和传递,是否有将const char *转换回类型说明符的函数?喜欢:

int a = 1;
auto t = typeid(a).name();
some_function(t) b = 1; //gives int b

我知道decltype确实可以做到这一点,但是它不能“存储”类型说明符。

在我最近的项目中,我遇到了一个奇怪的案例,其中每次调用时函数参数的类型可能会有所不同。通常,使用函数模板是可以的,但是它要么需要将所有代码放在该项目中不允许的标头中,要么使用显式实例化,因为很难列出所有类型,因此可能会造成混乱。另外,为每种类型编写多个函数重载也很麻烦。

如果有一种方法可以将类型说明符存储为变量,那么我可以使用void *传递输入的地址,并将包含类型说明符的变量传递给函数,然后将void *转换回其原始类型?

以某种方式,typeid()。names()已经提供了一种存储和传递变量类型的方法,我想知道是否存在一种优雅的方法可以将其转换回类型说明符,而无需编写长长的“ strcmp”或其他列表手动转换。

谢谢!

编辑: 关于我的项目的更多信息,该函数用作私有类成员的设置器,第一个输入是有关成员ID的枚举,第二个是值。该类也可以被继承。该项目要求在标头中放置尽可能少的代码。此项目使用OpenCV。

在Header.h中:

#include "some_other_custom_class.h"
#include <string>

enum BASE_PARA
{
    A,
    B,
    C
}
class Base
{
public:
    Base() = default;
    virtual ~Base() = default;

    //<sometype> may vary regarding the member
    virtual void Set(const int& id, const <sometype>& value);

private:
    int a;
    float b;
    map<std::string, double> c;
}

enum DERIVED_A_PARA
{
    D,
    E
}
class DerivedA : public Base
{
public:
    //inherit Set()
    virtual void Set(const int& id, const <sometype>& value) override;

private:
    map<int, <some_custom_class>> d;
    vector<double> e;
}

class DerivedB : public DerivedA //and so on
{
}

在Cpp.cpp中:

void Base::Set(const int& id, const <sometype>& value)
{
    //processing the input regarding the private member

    //<do something here>

    switch(id)
    {
    default:
        break;
    case A:
        a = value;//which means in here <sometype> should be int
        break;
    case B:
        b = value;//<sometype> should be float
        break;
    case C:
        //<sometype> should be map<string, double>
        if (<some_code_to_ensure_value_is_not_empty>)
            return;
        c["first"] = value["first"];
        c["second"] = value["first"] + value["second"];
        break;
    }
}

void DerivedA::Set(const int& id, const <sometype>& value)
{
    //something like above
}

我知道函数模板对此很有用,但是不能如上所述使用它。因此,我希望将“ sometype”更改为void *以指向地址,并从typeid()。name()生成的const char *标记为实际类型。但是我找不到将const char *转换回类型说明符的好方法。

1 个答案:

答案 0 :(得分:2)

共有三个选项

  1. 过载集,
  2. 功能模板或
  3. 类型擦除

但是在某些时候,您要么必须使用模板,要么编写一定数量的样板文件/重载/分支。

[a]类型的函数参数[可能]变化”的最佳选择是函数模板,因为这基本上是模板的用例。

如果它们不能位于项目的(可能是)公共头文件中,则可能会产生某种内部头文件。如果仅在特定位置使用代码,则可以在源文件内定义模板(以提高可重用性)。


C ++ 17中的

std::any是一种用于类型擦除的语法糖,如果您强制转换为{所不支持的类型,则它可以通过std :: bad_any_cast异常为您提供更优雅的类型擦除{1}}。

any