具有前向引用和运算符 += 的可变参数模板



我有一个函数,它应该接受几个参数,将所有参数添加到*this后,operator+=被重载并适用于一个参数。函数看起来像

template <typename T, typename U>
struct are_equal :
std::is_same<typename std::decay<T>::type, U>::type
{};
template<typename T>
template<typename... U>
std::enable_if_t<are_equal<U ..., Object<T>>::value>
Object<T>::addd(U &&... u)
{
//  *this += std::forward<U>(u)...;
}

可能我有两个问题。 1.我认为我应该用type_traits更改部分代码,但是我的实验没有给出正确的结果。 注释行出错(其中operator +=

(

C2893 无法专用函数模板"enable_if<_Test,_Ty>::类型对象::添加(U &&...(" C2672 "对象::已添加":未找到匹配的重载函数

  1. 注释行中的字典(?(问题:

    *this += std::forward<U>(u)...;
    

错误:

C2143 语法错误:在"..."之前缺少";">

C2059 语法错误:"...">

C3520 'u':在此上下文中必须扩展参数包

Operator+=一个元素工作正常(我敢肯定(。

我假设您希望该包扩展产生如下所示的内容:

*this += std::forward<U>(u_1),
*this += std::forward<U>(u_2),
// ...
*this += std::forward<U>(u_n);

*this += std::forward<U>(u)...;不起作用的原因是,粗略地说,由包扩展(但不是由折叠表达式,见下文(产生的逗号不能用作运算符

C++17 之前的经典解决方法是使用虚拟数组:

using dummy_array = int[];
dummy_array{(*this += std::forward<U>(u), 0)..., 0};

请注意,此扩展生成的逗号不用作运算符(而是用作元素初始值设定项的分隔符(,因此不应用上述限制。

上面代码片段中的第一个, 0让我们忽略返回类型*this += blah.
第二个, 0用于支持空参数包(否则会尝试创建一个空数组,这是不允许的(。

类型别名是必需的,因为编译器不允许直接使用int[]{blah, blah}

作为using的替代方案,您可以使用类似的东西

std::enable_if_t<1, int[]>{(std::cout << p, 0)..., 0};

另一种选择是创建一个实际的数组而不是临时数组:

int dummy_array[]{(std::cout << p, 0)..., 0};
(void)dummy_array;

但我不太喜欢这个。


如果您有 C++17,则应改用折叠表达式:

((*this += std::forward<U>(u)), ...);

我认为您想要以下内容:

template <bool ... Bs> struct bools {};
template <bool ... Bs>
using all_of = std::is_same<bools<true, Bs...>, bools<Bs..., true>>;
template <typename T, typename ... Ts>
using are_equal = all_of<std::is_same<T, Ts>::value...>;
template<typename T>
template<typename... Us>
std::enable_if_t<are_equal<T, std::decay_t<Us>...>::value>
Object<T>::add(Us&&... u)
{
const int dummy[] = {0, ((*this += std::forward<Us>(u)), 0)...};
static_cast<void>(dummy);
}

相关内容

  • 没有找到相关文章

最新更新