使用枚举值编译访问元组项目的时间
我想使用枚举值作为索引访问元组项。 我读过这篇文章来帮忙。
我在VS2013工作,因此我不能使用C ++ 14非常方便的auto
而无需trailing return
。
静态转换工作,但它很麻烦,也需要元组自由访问(在实际代码属性在protected
范围内)。
我想通过使用模板化方法GetAttribute
来改善这一点。
我试过这个,但是它产生了一个错误:
prog.cpp:30:119:错误:无效操作数的类型''和'size_t {aka unsigned int}'到二进制'操作符''自动GetAttribute(AttributeName属性名称) - > decltype(std :: declval(std :: get (attributeName)>(attributes)))^ prog.cpp:30:119:error:类型''和'size_t {aka unsigned int}'的操作数无效到二元运算符''prog.cpp:在函数'int main ()':prog.cpp:57:4:error:'struct X'has no member named'GetAttribute'x.GetAttribute(XParameters :: PARAMETER1); //不编译。 ^
现场演示
#include <tuple>
#include <cstddef>
#include <utility>
#include <iostream>
enum class XParameters : unsigned int
{
PARAMETER1, // int
PARAMETER2, // float
MAX,
};
enum class YParameters : unsigned int
{
PARAMETER3 = XParameters::MAX // std::string
};
using XTuple = std::tuple<int, float>;
using YAttributes = std::tuple<std::string>;
using YTuple = decltype(tuple_cat(XTuple(), YAttributes()));
template <typename Attributes>
struct Common
{
Common(Attributes&& attr) : attributes(std::move(attr)) {}
Attributes attributes;
template <typename AttributeName>
auto GetAttribute(AttributeName attributeName) -> decltype(std::declval(std::get<static_cast<size_t>(attributeName)>(attributes)))
{
return std::get<static_cast<size_t>(attributeName)>(attributes);
}
};
struct X : Common<XTuple>
{
X() : Common(std::make_tuple(42, 3.14f)) {}
};
struct Y : Common<YTuple>
{
Y() : Common(std::make_tuple(666, 0.01f, "string")) {}
};
int main()
{
X x;
Y y;
int parameter1 = std::get<static_cast<size_t>(XParameters::PARAMETER1)>(x.attributes); // Compiles, works.
std::cout << parameter1 << std::endl;
std::string parameter3 = std::get<static_cast<size_t>(YParameters::PARAMETER3)>(y.attributes); // Compiles, works.
std::cout << parameter3 << std::endl;
// Shorter code
x.GetAttribute(XParameters::PARAMETER1); // Does not compile.
//parameter3 = std::get<static_cast<size_t>(YParameters::PARAMETER3)>(x.attributes); // Does not compile, phew...
return 0;
}
恐怕没有漂亮的解决方案。
丑陋的变体 - 在呼叫站点投射
实现类似的最简单的方法是将值作为非类型模板参数传递:
template <size_t attributeName>
auto GetAttribute() -> decltype(std::get<attributeName>(attributes))
{
return std::get<attributeName>(attributes);
}
这会使电话变得丑陋,因为你必须在那里演员:
x.GetAttribute<static_cast<size_t>(XParameters::PARAMETER1)>();
不是那么丑陋的变体 - 关联的枚举类型
您可以通过将枚举类型与Common类相关联来解决这个问题:
template <typename Attributes, typename EnumType>
struct Common
{
Common(Attributes&& attr) : attributes(std::move(attr)) {}
Attributes attributes;
template <size_t attributeName>
auto GetAttribute() -> decltype(std::get<attributeName>(attributes))
{
return std::get<attributeName>(attributes);
}
template <EnumType attributeName>
auto GetAttribute() -> decltype(GetAttribute<static_cast<size_t>(attributeName)>())
{
return GetAttribute<static_cast<size_t>(attributeName)>();
}
};
这将允许这样的调用:
struct X : Common<XTuple, XParameters>
{
X() : Common(std::make_tuple(42, 3.14f)) {}
};
x.GetAttribute<XParameters::PARAMETER1>();
显然,您需要为每个Common实例专门设置一个枚举。
最佳变体(?) - 免费(重载)功能
在这种情况下,您只需使用原始元组。 然后你滚动你自己的函数(例如GetAttribute
),你为你的特定类型的元组和枚举重载:
template <XParameters attributeName>
auto GetAttribute(XTuple &tuple) -> decltype(std::get<static_cast<size_t>(attributeName)>(tuple) )
{
return std::get<static_cast<size_t>(attributeName)>(tuple);
}
GetAttribute<XParameters::PARAMETER1>(x.attributes);
在这种情况下定义GetAttribute
有很多样板代码,所以你可能想把它隐藏在宏后面:
#define DEFINE_GetAttribute(ENUM_TYPE, TUPLE_TYPE)
template <ENUM_TYPE attributeName>
auto GetAttribute(TUPLE_TYPE &tuple)
->decltype(std::get<static_cast<size_t>(attributeName)>(tuple)) {
return std::get<static_cast<size_t>(attributeName)>(tuple);
}
DEFINE_GetAttribute(XParameters, XTuple)
链接地址: http://www.djcxy.com/p/90831.html
上一篇: Compile time access to tuple item with an enum value
下一篇: C++11 type trait to differentiate between enum class and regular enum