参数包列表展开导致可变构造函数重载失败
Parameter pack list expansion causes variadic constructor overload to fail
我有一个具有两个可变构造函数的结构体,其区别在于在第二个构造函数的前面存在一个单独的int const*
参数:
struct S
{
template<class... Args> S(Args... args)
{
int arr[sizeof...(args)] = { args... }; // [A]
}
template<class... Args> S(int const *p, Args... args) {} // [B]
};
int main()
{
int i = 1;
S s(&i, 1, 2); // [C]
return 0;
}
使用Visual c++ 2015,行[A]导致:error C2440: 'initializing': cannot convert from 'int *' to 'int'
。如果我注释掉行[A],那么它编译得很好,[C]调用[B],所以似乎初始化列表的存在导致编译器查看函数内部并贪婪地尝试将所有参数转换为int
,忽略解释[B]。
如果我保留[A],但将[C]中的构造函数调用更改为S s((int const*)&i, 1, 2);
,那么它也可以编译,因此[A]似乎可以防止从int*
到int const*
的隐式转换,这通常适用于常规函数。
如果我不想在所有构造函数调用中显式地对指针进行const强制转换,而不是使用[A]行,我可以使用递归函数将参数pack解包为int数组,但这样更混乱。最简单的解决方案是将[B]更改为template<class... Args> S(int *p, Args... args) {}
,但这样就隐藏了我不更改*p
的意图。
选择[A]的原因是参数包可以完全匹配int*
,因此不需要const转换就可以得到[B]。
一个选择是使用一个重载的帮助器来简单地提供一个"值getter",你可以在参数包上调用它:
int get_value_impl(int _in)
{
return _in;
}
int get_value_impl(const int* _in)
{
return *_in;
}
struct S
{
template<class... Args> S(Args... args)
{
int arr[sizeof...(args)] = { get_value_impl(args)... }; // [A]
}
};
int main()
{
int i = 1;
S s(&i, 1, 2); // [C]
return 0;
}
现在你根本不需要[B]了。
如果你有更多的类型,你可以添加更多的重载到get_value_impl
,你将保留S
的结构。如果事情变得比这更复杂,您可能需要考虑使用SFINAE来选择get_value_impl
的实现。我认为这种解决方案是一种更简单的标记分派。演示
重载可变模板会变得非常糟糕。一种选择是添加一个重载,它接受一个int*
并委托给int const*
构造函数:
template<class... Args> S(int *p, Args... args) :
S(static_cast<int const*>(p), args...) { }
在这种情况下,如果你要传递大的类,你可能要考虑完美转发args
。
这是因为它选择的是第一个构造函数,而不是第二个。原因是&i
绑定了int* const
的引用。
你能做的是使用type_traits来选择变量,像这样(c++ 14):
template<typename First, typename ...Args>
S(T && t, Args && ...args) :
S( std::is_same<int,std::remove_reference_t<std::remove_cv<T>>>(),
std::forward<T>(t), std::forward<Args>(args)...) {}
template<typename ...Args>
S(std::false_type, int* const p, Args&&...args) //[A]
template<typename ...Args>
S(std::true_type, Args&&...args) //[B]
- 为什么除非添加括号,否则构造函数上的模板替换会失败?
- 在构造函数中分配内存失败是如何冒泡的
- 函数返回时,带指针的复制构造函数失败
- MPICH 的 MPI_Comm_dup() 在复制构造函数中失败
- 引用构造函数时链接失败
- 类模板在其构造函数中的模板变量推导失败
- 构造函数SFINAE和继承在clang中失败
- 为什么即使直接构造函数有效,template_back也会失败
- 在 if 语句中调用重载构造函数失败
- 继承的构造函数,在 clang++3.9 中编译,在 g++ 7 中失败
- C++模板化类默认构造函数失败
- STD :: MAP EMPLECE通过显式构造函数失败
- 打开不存在的文件时如何使流构造函数失败?
- 复制构造函数失败..重载,动态分配
- 如何处理 RAII 的构造函数失败
- C++unique_ptr作为成员的模板的构造函数失败
- 如何使用new(std::nothrow)使构造函数失败
- 在stl列表中调用构造函数失败
- 尽管类名与C++完全匹配,但模板基类初始化构造函数失败
- 尝试在类成员初始化中使用 vector 的填充构造函数失败。怎么了?