C++ 模板推断给我一个通用引用的错误
为了真正理解C++17折叠表达式,我为容器编写了一个函数append:C++ 模板推断给我一个通用引用的错误,c++,templates,c++17,C++,Templates,C++17,为了真正理解C++17折叠表达式,我为容器编写了一个函数append: #include <iostream> #include <vector> #include <list> // fold expression template<typename T, typename U, template<typename> typename... Args> inline void append_impl(std::vector<T
#include <iostream>
#include <vector>
#include <list>
// fold expression
template<typename T, typename U, template<typename> typename... Args>
inline void append_impl(std::vector<T>& v, Args<U>... args) noexcept
{
static_assert((std::is_constructible_v<T,U>));
std::cout << "append_impl version one " << std::endl;
(v.insert(std::end(v),
std::begin(args),
std::end (args)), ...);
}
//fold expression
template<typename T, typename... Args>
inline void append_impl(std::vector<T>& v, Args&&... args) noexcept
{
static_assert((std::is_constructible_v<T, Args&&> && ...));
std::cout << "append_impl version two " << std::endl;
(v.push_back(std::forward<Args>(args)), ...);
}
// fold expression
template<typename T, typename... Args>
inline void append(std::vector<T>& v, Args&&... args) noexcept
{
(append_impl(v, args), ...);
}
int main()
{
std::vector<int> a = {1,2};
std::vector<int> b = {3,4};
std::vector<int> c = {5,6};
std::list<int> d = {15,16};
append(a,b,c, std::vector<int>{8,9}, 10, 11, 12, 13, 14, d);
for(const auto& e : a)
{
std::cout << e << " ";
}
std::cout << std::endl;
return 0;
}
这很好,给我一个结果:
附加\u impl版本1
附加\u impl版本1
附加\u impl版本1
附加\u impl版本2
附加\u impl版本2
附加\u impl版本2
附加\u impl版本2
附加\u impl版本2
附加\u impl版本1
12345689101121314141516
但我有一个问题来自于这段代码:
在append_impl的第一个版本中,args是按副本传递的。我想在Scott Meyers sens中使用通用引用来避免这种情况,但是附加了_implst::vector&v,Args&&。。。args给我一个编译错误。
为什么以及如何避免复制?您的代码存在以下问题: 你忘了包括在内 您忘记在“附加”中转发: 但是,您有一个问题,即非常量左值引用更适合直接使用Args&&的第二个模板重载,因此您需要添加另一个重载:
template<typename T, typename U, template<typename...> typename... Args>
inline void append_impl(std::vector<T>& v, Args<U>&... args) noexcept
{
append_impl(v, std::as_const(args)...);
}
要求包括
通常,您试图识别容器的方式是不保存的。对于所有由模板类构成且不是容器的类型,它都将失败
相反,您可以通过SFINAE在将要使用的容器接口上选择正确的函数重载,即std::beginarg、std::endarg和insert调用。你可以用它来做
或者,您可以为这些表达式的良好格式编写一个类型特征,并为append\u impl使用一个重载,该重载基于检查类型特征的if constexpr选择实现
在C++20中,这将以更简单的方式实现,使用概念
似乎也没有任何理由认为append_impl将Args作为参数包。对于Args,只能使用一个参数调用它。如果您的代码出现错误,请将该代码及其错误告诉我们。是的,抱歉,完成了。
(append_impl(v, std::forward<Args>(args)), ...);
template<typename T, typename U, template<typename...> typename... Args>
inline void append_impl(std::vector<T>& v, const Args<U>&... args) noexcept
template<typename T, typename U, template<typename...> typename... Args>
inline void append_impl(std::vector<T>& v, Args<U>&&... args) noexcept
template<typename T, typename U, template<typename...> typename... Args>
inline void append_impl(std::vector<T>& v, Args<U>&... args) noexcept
{
append_impl(v, std::as_const(args)...);
}