c++ - 通过使用显式构造函数将相同的参数传递给每个元素来构造元组

标签 c++ constructor tuples variadic-templates explicit

以下代码在 Visual C++ 2015 Update 2 上运行良好。请注意 A是不可复制的并且A::Aexplicit .

#include <iostream>
#include <tuple>

struct A
{
    explicit A(int i)
    {
        std::cout << i << " ";
    }

    // non-copyable
    A(const A&) = delete;
    A& operator=(const A&) = delete;
};


template <class... Ts>
struct B
{
    std::tuple<Ts...> ts;

    B(int i)
      : ts((sizeof(Ts), i)...)
    {
    }
};


int main()
{
    B<A, A, A, A> b(42);
}

目标是将相同的参数传递给所有元组元素。它正确输出:

42 42 42 42

但是,它无法在 g++ 4.9.2 上编译。在众多消息中有一条tuple。我认为应该调用的构造函数重载:

In instantiation of ‘B<Ts>::B(int) [with Ts = {A, A, A, A}]’:
    33:24:   required from here
    25:30: error: no matching function for call to
       ‘std::tuple<A, A, A, A>::tuple(int&, int&, int&, int&)’
          : ts((sizeof(Ts), i)...)

[...]

/usr/include/c++/4.9/tuple:406:19: note: template<class ... _UElements, class>
    constexpr std::tuple< <template-parameter-1-1> >::tuple(_UElements&& ...)
     constexpr tuple(_UElements&&... __elements)
               ^
/usr/include/c++/4.9/tuple:406:19: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/tuple:402:40: error: no type named ‘type’ in
    ‘struct std::enable_if<false, void>’
       template<typename... _UElements, typename = typename

消息中的函数签名不完整,但指的是这个:

template<typename... _UElements, typename = typename               
   enable_if<__and_<is_convertible<_UElements,
                   _Elements>...>::value>::type>                        
explicit constexpr tuple(_UElements&&... _elements)                      
     : _Inherited(std::forward<_UElements>(__elements)...) { }    

我的理解是is_convertible显式构造函数失败。 g++ 5.1 和 clang 3.5 也有类似的错误信息。

现在,在 C++14 中,20.4.2.1/10 说:“除非 UTypes 中的每个类型都可以隐式转换为其在 Types 中的相应类型,否则此构造函数不应参与重载决策”。这给我的印象是 g++ 和 clang 实际上有这个权利,而 Visual C++ 过于宽松。

[编辑:C++17 似乎已经取消了这个限制,而 Visual C++ 2015 也遵循了它。它现在说:“除非 [...] is_constructible<Ti, Ui&&>::value 对所有 true 都是 i,否则此构造函数不应参与重载决议。”看起来“可隐式转换”已更改为“is_constructible”。但是,我仍然需要一个 C++14 解决方案。]

我尝试删除 explicit来自构造函数(我宁愿保留它)。 Visual C++ 再次编译正常,但 g++ 和 clang 都提示删除了复制构造函数。因为int现在可以隐式转换为 A , 我似乎结束了

explicit constexpr tuple(const Types&...)

这将隐式转换 int变成一堆A s 然后尝试复制它们。我实际上不确定我将如何使用其他构造函数。

在 C++14 中,我如何获得 tuple如果构造函数是 explicit,则通过将相同的参数传递给每个构造函数来初始化其元素?

最佳答案

在 C++ 14 中,由于 is_convertible 要求,当构造函数是显式时,似乎没有任何方法可以初始化元组元素。我最终自己编写了 std::tuple 的基本实现,用于 C++14 实现,例如 Debian 8。

关于c++ - 通过使用显式构造函数将相同的参数传递给每个元素来构造元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36580855/

相关文章:

javascript - 将 QJsonObject 转换为 Javascript 对象

c++ - 与 Java 无关的 list 文件是什么?

c++ - 带有 clSetKernelArg 的 OpenCL 竞争条件

java - Java构造函数和线程安全

Python 使用 lambda 修改元组

Scala:元组的并行分配

c++ - 在将数组传递给 printf 等可变参数函数时,我应该将数组转换为指针吗?

派生类型的构造函数

java - 这个 Java 文件中的构造函数在做什么?

c++ - 构造 std::tuple 时定义元素初始化顺序