C++ - 迭代元组和类型解析与常量参数

标签 c++ c++11 tuples enable-if

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

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);
}

不幸的是,当我试图调用运算符时,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:   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 ...>&)

这很奇怪,因为 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 >(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);
}

这会按预期进行编译和工作。为什么简化版拒绝编译?谢谢。

最佳答案

对函数或类模板使用显式指定的模板参数需要任何模板参数包出现在整个模板参数列表的末尾。将 Ts... 移动到模板参数列表的末尾并适本地更改调用可以使代码正常工作。 the current C++0x draft 的第 14.8.2.1 节声明不在模板参数列表末尾的参数包不能从函数调用中推断出来(这会使您的原始代码失败),但明确指定所有模板参数到 operator+=所有情况仍然会导致 SFINAE 错误。 A previous question有指向禁止它的确切文本的链接; IBM's documentation说这也是一个错误。

关于C++ - 迭代元组和类型解析与常量参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4832949/

相关文章:

c++ - (C/C++) 结构包含包含结构的 union ...?

c++ - 获取 istringstream 的未读部分

python - 使用 sum() 连接元组

python - 返回元组列表中的唯一记录以及具有最大日期时间的非唯一记录

c++ - C++中继承重定义函数的实际含义

c++ - 当我们在 C++ 中更改字符串的值时会发生什么

c++ - cmake 获取源列表

c++ - 如何使线程访问类的私有(private)成员

c++ - C++ 条件语句是否带有从条件表达式到语句的依赖关系?

Python:在元组上使用 lower 函数