English 中文(简体)
std::get 使用 enum 类作为模板参数
原标题:std::get using enum class as template argument

我使用std::tuple , 并定义了一种类 enum, 以某种方式“命名”每个 tupple 字段, 忘记了它们的实际索引 。

因此,与其这样做:

std::tuple<A,B> tup;
/* ... */
std::get<0>(tup) = bleh; // was it 0, or 1?

我做了这个:

enum class Something {
     MY_INDEX_NAME = 0,
     OTHER_INDEX_NAME
};

std::tuple<A,B> tup;
/* ... */
std::get<Something::MY_INDEX_NAME> = 0; // I don t mind the actual index...

问题是,由于这是用 gcc 4.5.2 编译的,我现在安装了4.6.1 版本,我的工程没有编译。

#include <tuple>
#include <iostream>

enum class Bad {
    BAD = 0
};

enum Good {
    GOOD = 0
};

int main() {
    std::tuple<int, int> tup(1, 10);
    std::cout << std::get<0>(tup) << std::endl;
    std::cout << std::get<GOOD>(tup) << std::endl; // It s OK
    std::cout << std::get<Bad::BAD>(tup) << std::endl; // NOT!
}

错误基本上表示没有超载符合我调用 std:: get 的调用 :

test.cpp: In function ‘int main()’:
test.cpp:16:40: error: no matching function for call to ‘get(std::tuple<int, int>&)’
test.cpp:16:40: note: candidates are:
/usr/include/c++/4.6/utility:133:5: note: template<unsigned int _Int, class _Tp1, class _Tp2> typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(std::pair<_Tp1, _Tp2>&)
/usr/include/c++/4.6/utility:138:5: note: template<unsigned int _Int, class _Tp1, class _Tp2> const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(const std::pair<_Tp1, _Tp2>&)
/usr/include/c++/4.6/tuple:531:5: note: template<unsigned int __i, class ... _Elements> typename std::__add_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(std::tuple<_Elements ...>&)
/usr/include/c++/4.6/tuple:538:5: note: template<unsigned int __i, class ... _Elements> typename std::__add_c_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(const std::tuple<_Elements ...>&)

那么,有没有办法我可以用我的昆虫类作为模板参数来表示std::get ?这不是要编译的,而是在Gcc 4.6中固定的?我可以使用一个简单的昆虫,但是我喜欢昆虫类的范围属性,所以如果可能,我宁愿使用后者。

最佳回答

C++11 引入的强烈型号enum 不能隐含地转换成类型中的整体值, 包括 < code> < int , 而 < code>std:: get 则预计模板参数为整体类型 。

您需要使用 static_cast 转换 enum 值 :

std::cout <<std::get<static_cast<int>(Bad::BAD)>(tup)<< std::endl; //Ok now!

或者您可以选择转换为 :

//note that it is constexpr function
template <typename T>
constexpr typename std::underlying_type<T>::type integral(T value) 
{
    return static_cast<typename std::underlying_type<T>::type>(value);
}

然后使用它作为:

std::cout <<std::get<integral(Bad::BAD)>(tup)<< std::endl; //Ok now!
问题回答

我想补充另一个答案, 因为最初的海报要求一种方式,

有可能有一个分类 enum 类型的模板参数( 至少在 GCC 中 ) 。 这样可以定义您自己的 < code>get 获取 Tuple 元素的元素, 给一个类 enum 值 。 下面是显示此值的操作, 但您也可以做一些更花哨的事情 :

#include <tuple>

enum class names { A = 0, B, C };

template< names n, class... Types >
typename std::tuple_element<static_cast< std::size_t >( n ), std::tuple<Types...> >::type&
    get( std::tuple<Types...>& t )
{
    return std::get< static_cast< std::size_t >( n ), Types... >( t );
}

int main( int, char** )
{
    std::tuple< char, char, char > t(  a ,  b ,  c  );
    char c = get<names::A>( t );
}

注意 < a href=" "http://en.cppreference.com/w/cpp/utility/tuple/get" rel=" noreferrer"\\ code>std:::: get 有两个其他的变体(一个是 const tuple& ,一个是 tupple&& ),这些变体可以完全相同的方式执行。

是的,这是海合会4.5中的一个错误。

一个完全不同的解决办法是:

A& my_field(std::tuple<A,B>& t) { return std::get<0>(t); }
A const& my_field(std::tuple<A,B> const& t) { return std::get<0>(t); }

B& my_other_field(std::tuple<A,B>& t) { return std::get<1>(t); }
B const& my_other_field(std::tuple<A,B> const& t) { return std::get<1>(t); }

my_field(t) = blah;
my_other_field(t) = frob;

2018年更新 :

这已经不是问题了。我尝试变换“ enum level int ” 时,我确实有问题,但现在这与VS 2017 15. 7.2有效。

enum 
{
  WIDTH,
  HEIGHT
};
std::get<HEIGHT>( Remaining ) = std::get<HEIGHT>( Remaining ) - MinHeight;

重新定义标准:get?

namespace smthg {

template<auto EV, class... Types>
requires std::is_enum_v<decltype(EV)>
constexpr auto const& get(std::tuple<Types...> const& t) noexcept
{
    return std::get<std::to_underlying(EV)>(t);
}

template<auto EV, class... Types>
requires std::is_enum_v<decltype(EV)>
constexpr auto& get(std::tuple<Types...>& t) noexcept
{
    return std::get<std::to_underlying(EV)>(t);
}

}

enum class side { LEFT, RIGHT };
std::tuple<int, int> a {5, 3};

assert(smthg::get<side::LEFT>(a) == 5);

参考文献也必须重新定义。

我的解决办法是使用:

namespace Something{enum class Something {MY_INDEX_NAME = 0,OTHER_INDEX_NAME};};




相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签