通过字符串模板参数获取元组的访问权限

3

C++11 的标准元组支持通过整数模板参数访问,如下所示:

tuple<int, double> test;
test.get<1>();

但如果我想通过字符串模板参数获得访问权限:

test.get<"first">()

如何实现它?

首先,它是 std::get<1>(test)(好的,在 C++1z 中可能会更改)。其次,您不能像这样为模板参数获取指针。最后,为什么要使用 c 字符串字面值而不是索引? - Jarod42
如果你想要一个运行时字符串是不可能的。如果你想要一个静态字符串,可以使用 boost::fusion::map 中的 type_tags 等更好的选项。 - alfC
在下一步中,我想要为数据库协处理器实现关系类。 数据库表中的列称为字符串名称。 - COUNTERKILL
@COUNTERKILL 那为什么不使用 std::map 而不是 std::tuple 呢?这样你就可以写成 test["first"] - mikedu95
不同的数据库列可以有不同的类型。如果我使用std::map,我无法获得对所有列的相同访问权限。 - COUNTERKILL
你知道编译时的类型吗?如果不知道,你可以使用 std::map<std::string, boost::any> 或者 std::map<std::string, boost::variant>。(看一下 boost::property_tree)。 - alfC
3个回答

1
你可以创建自定义的constexpr转换函数。我只是想展示OP想要的(几乎)是可能的。
#include <tuple>
#include <cstring>

constexpr size_t my_cast(const char * text)
{
    return !std::strcmp(text, "first") ? 1 :
           !std::strcmp(text, "second") ? 2 :
           !std::strcmp(text, "third") ? 3 :
           !std::strcmp(text, "fourth") ? 4 :
           5;
}

int main()
{
    std::tuple<int, double> test;
    std::get<my_cast("first")>(test);
    return 0;
}

这可以在GCC 4.9.2中使用C++11(C++14)编译。在Visual Studio 2015中无法编译。


0
首先,std::tuple::get不是成员函数。有一个非成员函数std::get
鉴于此,
std::tuple<int, double> test;

你不能使用以下方式获取第一个元素:

std::get<"first">(test);

你可以使用其他助记符:

const int First = 0;
const int Second = 1;
std::get<First>(test);
std::get<Second>(test);

如果这样做能让代码更易读。

-1
R Sahu提供了一些好的助记符,我想再添加一个。您可以使用C风格的枚举(即非类枚举):
enum TupleColumns { FIRST, SECOND };

std::get<FIRST>(test);

如果您将枚举与智能枚举反射库(例如:https://github.com/krabicezpapundeklu/smart_enum)结合使用,那么您可以创建一组具有自动转换为字符串的枚举。因此,您可以自动将列名转换为枚举并以此访问元组。
所有这些都要求您在编译时提交您的列名和顺序。此外,您始终需要使用字符串字面量或constexpr函数,以便您可以将枚举值作为constexpr获取并以此方式使用它。
constexpr TupleColumns f(const char *);
constexpr auto e = f("first");
std::get<e>(test);

在这里我应该加上一个警告:这是一个相当深的兔子洞,需要相当强的C++知识。在更大的视角中,我可能会寻找不同的解决方案,但我不太清楚你的更大的视角,也不知道你的C++水平和同事们的水平(假设你有同事)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接