是否有可能通过重复的std :: tuple的类型名称获取?

时间:2016-08-12 13:42:52

标签: c++ c++11

using Name = std::string;
using NodeType = int;
using ElementType = int;

std::tuple<Name, NodeType, ElementType> myTuple("hi", 12, 42);

cout<<std::get<NodeType>(myTuple)<<endl;

这会产生编译错误。

我可以使用std::get<1>(myTuple),但它不容易被理解为std::get<NodeType>(myTuple),在这种情况下有什么方法可以按类型获取值?

5 个答案:

答案 0 :(得分:7)

NodeTypeElementType属于同一类型,即inttypedefusing不会创建新类型,只会创建名称。

所以不,你不能按类型获得最后一个条目,因为它们的类型在元组中不是唯一的。

答案 1 :(得分:4)

enum {NodeTypeIdX=1, ElementTypeIdx=2};

std::get<NodeTypeIdx>(myTuple);

这可以自我记录。

std::get<Type>语法不支持std::get<Type, which_one>或类似内容。它仅在类型唯一时才有效。由于您无法控制元组的定义,因此您无法(已定义)使std::get<Type>选项有效。

另一方面,谁在乎您使用的关键字是类型还是枚举常量?重要的是它有一个自我记录的名称。

答案 2 :(得分:1)

无论您如何命名,类型都是相同的 - propsintElementType是等效的,并且无法区分它们。

我会编写访问器函数并使用它们:

NodeType

答案 3 :(得分:0)

假设NameNodeTypeElementType 不同的类型(标签可能有帮助):

template <class T>
struct Names;

template <> struct Names<Name> { static constexpr int i = 0; };
template <> struct Names<NodeType> { static constexpr int i = 1; };
template <> struct Names<ElementType> { static constexpr int i = 2; };

您可以使用辅助函数将其缩短一点:

template <class T>
constexpr auto index() -> int
{
    return Names<T>::index;
}

所以你得到:

cout<<  std::get< index<NodeType>() >(myTuple) <<  endl;

我会告诉你这不是最好的。

答案 4 :(得分:0)

正如其他答案中所提到的,如果std::get<int>(tuple)包含多个tuple int,则get<>()将不起作用,因此对您无效。

但是,您可以制作自己的my_get<Et,P>(tuple),它可以满足您的需求。以下代码定义了一个模板函数(P+1)th,它将返回对Et tuple类型的template<typename Et, size_t P, typename Ct, size_t N, typename Et2> typename std::enable_if<std::is_same<Et,Et2>::value && (P == 0), Et&>::type my_get(Ct& c, Et2& e) { return std::get<N>(c); } template<typename Et, size_t P, typename Ct, size_t N, typename Et2> typename std::enable_if<std::is_same<Et,Et2>::value && (P > 0), Et&>::type my_get(Ct& c, Et2& e) { return my_get<Et,P-1,Ct,N+1>(c); } template<typename Et, size_t P, typename Ct, size_t N, typename Et2> typename std::enable_if<!std::is_same<Et,Et2>::value, Et&>::type my_get(Ct& c, Et2& e) { return my_get<Et, P, Ct, N+1>(c, std::get<N+1>(c)); } template<typename Et, size_t P, typename Ct, size_t N> Et& my_get(Ct& c) { return my_get<Et, P, Ct, N>(c, std::get<N>(c)); } template<typename Et, size_t P, typename Ct> Et& my_get(Ct& c) { return my_get<Et, P, Ct, 0>(c); } 元素的引用。

void tptest()
{
    std::tuple<double,int,double,int> mytuple(1.0,2, 3.0, 4);
    std::cout << "my_get<double,0>(mytuple) = " << my_get<double,0>(mytuple) << std::endl;
    std::cout << "my_get<int,0>(mytuple)    = " << my_get<int,0>(mytuple) << std::endl;
    std::cout << "my_get<double,1>(mytuple) = " << my_get<double,1>(mytuple) << std::endl;
    std::cout << "my_get<int,1>(mytuple)    = " << my_get<int,1>(mytuple) << std::endl;
}

用法:

my_get<double,0>(mytuple) = 1
my_get<int,0>(mytuple)    = 2
my_get<double,1>(mytuple) = 3
my_get<int,1>(mytuple)    = 4

输出:

/Users/ghendrey/XXX/current/lib/libpcre.dylib', needed by