C ++ - 迭代一个元组&类型vs常数参数的分辨率 [英] C++ - Iterating over a tuple & resolution of type vs constant parameters

查看:199
本文介绍了C ++ - 迭代一个元组&类型vs常数参数的分辨率的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在为元组编写算术运算符重载。操作符遍历元组以对其每个元素执行操作。这里是operator + =的定义:

  template< typename ... Ts,std :: size_t I = 0> 
inline typename std :: enable_if< I == sizeof ...(Ts),std :: tuple< Ts ...> > :: type operator + =(std :: tuple< Ts ...& lhs,const std :: tuple< Ts ...& rhs)
{
return lhs;
}

template< typename ... Ts,std :: size_t I = 0>
inline typename std :: enable_if< I!= sizeof ...(Ts),std :: tuple< Ts ...> > :: type operator + =(std :: tuple< Ts ...& lhs,const std :: tuple< Ts ...& rhs)
{
std :: get< I>(1hs)+ = std :: get< (rhs);
return operator + =< Ts ...,I + 1>(1hs,rhs);不幸的是,当我尝试调用操作符时,GCC 4.6不能决定哪个过载它应该使用。例如:

  std :: tuple< int,int,int,int> a = std :: make_tuple(1,2,3,4),b = std :: make_tuple(5,6,7,8); 
a + = b;

产生以下错误:

 :/ Workspace / raster / main.cpp:833:7:从这里实例化
C:/Workspace/raster/main.cpp:809:45:error:调用'operator + =(std :: tuple< int,int,int,int>& const std :: tuple< int,int,int,int>&)'
C:/ Workspace / raster /main.cpp:809:45:note:candidate are:
C:/Workspace/raster/main.cpp:800:151:note:template< class ... Ts,unsigned int I> typename std :: enable_if<(I == sizeof(Ts ...)),std :: tuple< _TElements ...>&> :: type operator + =(std :: tuple< _TElements ...> ;& const std :: tuple< _TElements ...&)
C:/Workspace/raster/main.cpp:806:83:note:template< class ... Ts,unsigned int I> typename std :: enable_if<(I!= sizeof(Ts ...)),std :: tuple< _TElements ...>&> :: type operator + =(std :: tuple< _TElements ...> ;& const std :: tuple< _TElements ...>&)

奇怪,因为 std :: enable_if 条件应该拒绝不适当的调用。现在,我有以下解决方法,这实际上是我以前的实现。上述版本实际上是一个简化尝试。

  template< std :: size_t I,typename ... Ts> 
inline typename std :: enable_if< I == sizeof ...(Ts),std :: tuple< Ts ...> > :: type assignadd_impl(std :: tuple< Ts ...& lhs,const std :: tuple< Ts ...>& rhs)
{
return lhs;
}

template< std :: size_t I,typename ... Ts>
inline typename std :: enable_if< I!= sizeof ...(Ts),std :: tuple< Ts ...> > :: type assignadd_impl(std :: tuple< Ts ...& lhs,const std :: tuple< Ts ...>& rhs)
{
std :: get< I>(1hs)+ = std :: get< (rhs);
return assignadd_impl< I + 1,Ts ...>(1hs,rhs);
}

template<类型名... Ts>
inline std :: tuple< Ts ...> operator + =(std :: tuple< Ts ...& lhs,const std :: tuple< Ts ...>& rhs)
{
return assignadd_impl& 0,Ts ...>(1hs,rhs);
}

这样编译并按预期工作。为什么简化版拒绝编译?感谢。

解决方案

使用显式指定的模板参数到函数或类模板需要任何模板参数包出现在总体模板参数列表。将 Ts ... 移动到模板参数列表的末尾,并相应地更改调用使代码可以正常工作。 当前C ++ 0x的第14.8.2.1节草稿指出,不能从函数调用(这使您的原始代码失败)中推导出不在模板参数列表末尾的参数包,而是明确指定所有模板参数 operator + = 在所有情况下仍会导致SFINAE错误。 上一个问题有一个指向禁止其的确切文本的链接; IBM的文档说,这也是一个错误。


I'm currently in the process of writing arithmetic operator overloads for tuples. The operator iterates over the tuple to perform the operation on each of its individual element. Here is the definition for operator +=:

template< typename... Ts, std::size_t I = 0 >
inline typename std::enable_if< I == sizeof... (Ts), std::tuple< Ts... >& >::type operator +=(std::tuple< Ts... >& lhs, const std::tuple< Ts... >& rhs)
{
    return lhs;
}

template< typename... Ts, std::size_t I = 0 >
inline typename std::enable_if< I != sizeof... (Ts), std::tuple< Ts... >& >::type operator +=(std::tuple< Ts... >& lhs, const std::tuple< Ts... >& rhs)
{
    std::get< I >(lhs) += std::get< I >(rhs);
    return operator +=< Ts..., I + 1 >(lhs, rhs);
}

Unfortunately, when I attempt to call the operator, GCC 4.6 cannot decide which overload it should use. For example:

std::tuple< int, int, int, int > a = std::make_tuple(1, 2, 3, 4), b = std::make_tuple(5, 6, 7, 8);
a += b;

Yields the following error:

:/Workspace/raster/main.cpp:833:7:   instantiated from here
C:/Workspace/raster/main.cpp:809:45: error: no matching function for call to 'operator+=(std::tuple<int, int, int, int>&, const std::tuple<int, int, int, int>&)'
C:/Workspace/raster/main.cpp:809:45: note: candidates are:
C:/Workspace/raster/main.cpp:800:151: note: template<class ... Ts, unsigned int I> typename std::enable_if<(I == sizeof (Ts ...)), std::tuple<_TElements ...>&>::type operator+=(std::tuple<_TElements ...>&, const std::tuple<_TElements ...>&)
C:/Workspace/raster/main.cpp:806:83: note: template<class ... Ts, unsigned int I> typename std::enable_if<(I != sizeof (Ts ...)), std::tuple<_TElements ...>&>::type operator+=(std::tuple<_TElements ...>&, const std::tuple<_TElements ...>&)

Which is strange since the std::enable_if condition should reject the inappropriate call. For now, I have the following workaround which was actually my prior implementation. The above version is in fact a simplification attempt.

template< std::size_t I, typename... Ts >
inline typename std::enable_if< I == sizeof... (Ts), std::tuple< Ts... >& >::type assignadd_impl(std::tuple< Ts... >& lhs, const std::tuple< Ts... >& rhs)
{
    return lhs;
}

template< std::size_t I, typename... Ts >
inline typename std::enable_if< I != sizeof... (Ts), std::tuple< Ts... >& >::type assignadd_impl(std::tuple< Ts... >& lhs, const std::tuple< Ts... >& rhs)
{
    std::get< I >(lhs) += std::get< I >(rhs);
    return assignadd_impl< I + 1, Ts... >(lhs, rhs);
}

template< typename... Ts >
inline std::tuple< Ts... >& operator +=(std::tuple< Ts... >& lhs, const std::tuple< Ts... >& rhs)
{
    return assignadd_impl< 0, Ts... >(lhs, rhs);
}

This compiles and works as expected. Why does the simplified version refuse to compile? Thanks.

解决方案

Using explicitly specified template arguments to a function or class template requires that any template parameter packs appear at the end of the overall template parameter list. Moving Ts... to the end of the template parameter lists and changing the calls appropriately makes the code work. Section 14.8.2.1 of the current C++0x draft states that parameter packs that are not at the end of the template parameter list cannot be deduced from a function call (which makes your original code fail), but explicitly specifying all of the template arguments to operator+= in all cases still causes a SFINAE error. A previous question has a link to the exact text forbidding it; IBM's documentation says that it is an error as well.

这篇关于C ++ - 迭代一个元组&amp;类型vs常数参数的分辨率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆