通过字符串模板参数访问元组
Gaining access to the tuple by string template param
C++ 11 中的标准元组允许通过整数模板参数访问,如下所示:
tuple<int, double> test;
test.get<1>();
但是如果我想通过字符串模板参数访问:
test.get<"first">()
我该如何实施?
首先,std::tuple::get
不是成员函数。有一个 non-member 函数 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);
如果这样可以使代码更易读。
R Sahu 提供了几个很好的助记符,不过我想添加另一个。您可以使用 C 风格枚举(即 non-class 枚举):
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++ 水平和你的同事(假设你有他们)。
您可以创建自定义 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 年编译。
C++ 11 中的标准元组允许通过整数模板参数访问,如下所示:
tuple<int, double> test;
test.get<1>();
但是如果我想通过字符串模板参数访问:
test.get<"first">()
我该如何实施?
首先,std::tuple::get
不是成员函数。有一个 non-member 函数 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);
如果这样可以使代码更易读。
R Sahu 提供了几个很好的助记符,不过我想添加另一个。您可以使用 C 风格枚举(即 non-class 枚举):
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++ 水平和你的同事(假设你有他们)。
您可以创建自定义 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 年编译。