通过使用显式构造函数将相同的参数传递给每个元素来构造元组
Construct tuple by passing the same argument to each element with explicit constructor
以下在 Visual C++ 2015 Update 2 上运行良好。请注意,A
是不可复制的,A::A
是 explicit
。
#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 表示:"This constructor shall not participate in overload resolution unless each type in UTypes
is implicitly convertible to its corresponding type in Types
"。这给我的印象是g++和clang实际上有这个权利,而Visual C++过于宽松。
[edit: C++17 似乎已经取消了这个限制,Visual C++ 2015 也遵循了它。现在显示:"This constructor shall not participate in overload resolution unless [...] is_constructible<Ti, Ui&&>::value
is true
for all i
." 看起来 "is implicitly convertible" 已更改为“is_constructible
”。但是,我仍然需要一个 C++14 解决方案。]
我尝试从构造函数中删除 explicit
(我更愿意保留它)。 Visual C++ 再次编译正常,但 g++ 和 clang 都抱怨删除了复制构造函数。因为 int
现在可以隐式转换为 A
,我似乎最终变成了
explicit constexpr tuple(const Types&...)
这会将 int
隐式转换为一堆 A
,然后尝试复制它们。我实际上不确定我将如何使用其他构造函数。
在 C++14 中,如果构造函数是 explicit
,我如何通过将相同的参数传递给每个构造函数来让 tuple
初始化其元素?
在 C++ 14 中,由于 is_convertible
要求,当构造函数是显式时,似乎没有任何方法可以初始化元组元素。我最终自己编写了 std::tuple
的基本实现,用于 C++14 实现,例如 Debian 8。
以下在 Visual C++ 2015 Update 2 上运行良好。请注意,A
是不可复制的,A::A
是 explicit
。
#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 表示:"This constructor shall not participate in overload resolution unless each type in UTypes
is implicitly convertible to its corresponding type in Types
"。这给我的印象是g++和clang实际上有这个权利,而Visual C++过于宽松。
[edit: C++17 似乎已经取消了这个限制,Visual C++ 2015 也遵循了它。现在显示:"This constructor shall not participate in overload resolution unless [...] is_constructible<Ti, Ui&&>::value
is true
for all i
." 看起来 "is implicitly convertible" 已更改为“is_constructible
”。但是,我仍然需要一个 C++14 解决方案。]
我尝试从构造函数中删除 explicit
(我更愿意保留它)。 Visual C++ 再次编译正常,但 g++ 和 clang 都抱怨删除了复制构造函数。因为 int
现在可以隐式转换为 A
,我似乎最终变成了
explicit constexpr tuple(const Types&...)
这会将 int
隐式转换为一堆 A
,然后尝试复制它们。我实际上不确定我将如何使用其他构造函数。
在 C++14 中,如果构造函数是 explicit
,我如何通过将相同的参数传递给每个构造函数来让 tuple
初始化其元素?
在 C++ 14 中,由于 is_convertible
要求,当构造函数是显式时,似乎没有任何方法可以初始化元组元素。我最终自己编写了 std::tuple
的基本实现,用于 C++14 实现,例如 Debian 8。