我正在尝试创建类似于元组的东西,但是我遇到了编写构造函数的问题。
以下是代码:
#include <tuple>
template <typename... Ts>
struct B {
template <typename... ArgTypes>
explicit B(ArgTypes&&... args)
{
static_assert(sizeof...(Ts) == sizeof...(ArgTypes),
"Number of arguments does not match.");
}
};
struct MyType {
MyType() = delete;
MyType(int x, const char* y) {}
};
int main()
{
B <int, char> a{2, 'c'}; // works
B <int, bool, MyType, char> b{2, false, {4, "blub"}, 'c'}; // fails
std::tuple<int, bool, MyType, char> t{2, false, {4, "blub"}, 'c'}; // works
}
现在,如果将简单类型作为初始化程序传递,则可以正常工作,但如果我尝试在括号内的初始化程序列表中为非平凡对象传递参数,则不行。
GCC-4.7发出以下内容:
vararg_constr.cpp:21:67: error: no matching function for call to 'B<int, bool, MyType, char>::B(<brace-enclosed initializer list>)'
vararg_constr.cpp:21:67: note: candidates are:
vararg_constr.cpp:6:14: note: B<Ts>::B(ArgTypes&& ...) [with ArgTypes = {}; Ts = {int, bool, MyType, char}]
vararg_constr.cpp:6:14: note: candidate expects 0 arguments, 4 provided
Clang-3.1以下内容:
vararg_constr.cpp:21:40: error: no matching constructor for initialization of
'B<int, bool, MyType, char>'
B <int, bool, MyType, char> b{2, false,{4, "blub"}, 'c'}; // fails
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
vararg_constr.cpp:6:14: note: candidate constructor not viable: requires 2
arguments, but 4 were provided
explicit B(ArgTypes&&... args)
好的,现在是什么让我非常,非常好奇的是它适用于元组!根据标准(20.4.2.1),它有一个构造函数,看起来非常像我的。
template <class... Types>
class tuple {
public:
// ...
template <class... UTypes>
explicit tuple(UTypes&&...);
// ...
};
以相同的方式构造元组对象时,它可以工作!
现在我想知道:
A)到底是什么?为什么std :: tuple如此特殊,为什么编译器不能推断出正确数量的参数呢?
B)我怎样才能做到这一点?
答案 0 :(得分:6)
A)为什么编译器应该知道{4, "blub"}
是MyType类型而不是tuple<int, const char*>
?
B)在构造函数中将ArgTypes更改为Ts:
explicit B(Ts&&... args)
Tuple也有以下构造函数:
explicit constexpr tuple(const _Elements&... __elements);
编辑:重点是,const&amp;的构造函数被调用而不是R值。请考虑以下事项:
template <typename... Ts>
struct B {
explicit B(const Ts&... elements) { std::cout << "A\n"; }
template<typename... As,
typename = typename std::enable_if<sizeof...(As) == sizeof...(Ts)>::type>
explicit B(As&&... elements) { std::cout << "B\n" ;}
};
int main()
{
MyType m {1, "blub"};
B<int, char> a{2, 'c'}; // prints B
B<bool, MyType, char> b{false, {4, "blub"}, 'c'}; // prints A
B<bool, MyType, MyType>c{false, {4, "blub"}, std::move(m)}; // prints A
}