首页 > 解决方案 > 使用模板获取可以返回多种类型的方法

问题描述

为多个私有成员提供多种get方法会使一个类变得非常混乱。我想实现一个get能够返回我需要的任何成员的方法。

enum TYPE {INT, DOUBLE, DOUBLE2, STRING};

class Foo {
int i     = 1;
double d  = 2.5;
double d2 = 6.0;
string s  = "string";

public:

template<typename T>
T get(TYPE type) {
    switch (type) {
    case INT:
        return i;
    case DOUBLE:
        return d;
    case DOUBLE2:
        return d2;
    case STRING:
        return s;
    }
}

然后将像这样使用该方法:

Foo foo;
int integer = foo.get<int>(INT);
double d2   = foo.get<double>(DOUBLE2);

为什么编译不出来?

标签: c++templates

解决方案


你认为在这种情况下会发生什么?

TYPE t = DOUBLE;
if (rand() % 2 == 0) {
    t = INT;
}

int i = foo.get<int>(t); // t might be INT or DOUBLE

这是没有意义的,因为TYPE参数是一个运行时值,并且您依赖它来选择返回类型,这在编译时必须是已知的。

此外,当您执行该switch语句时,编译器必须编译整个 switch 语句,即使是可能不会被调用的情况。

想象一下get<int>被实例化的成员函数:

template<>
auto get<int>(TYPE type) -> int {
    switch (type) { // type might be anything
    case INT:
        return i;   // return int
    case DOUBLE:
        return d;   // return double
    case DOUBLE2:
        return d2;  // return double
    case STRING:
        return s;   // return string
    }
}

这无法编译。该函数清楚地返回一个int,但在某些分支中它返回其他类型。

一个适当的解决方案是完全删除枚举并使用类似constexpr if表示编译时分支的东西,而不是同时发送类型名和值,只依赖类型名。

如果您想了解有关如何实现这种数据结构的更多信息,我建议您阅读std::tuple


推荐阅读