在完美转发中,std::forward用于转换命名的右值引用t1和t2未命名的右值引用.这样做的目的是什么?inner如果我们离开t1&t2作为左值,那将如何影响被调用的函数?
template <typename T1, typename T2>
void outer(T1&& t1, T2&& t2)
{
inner(std::forward<T1>(t1), std::forward<T2>(t2));
}
Run Code Online (Sandbox Code Playgroud) 我已经看到多个代码实例,其中使用 && 表示法声明了函数参数包,如下所示,但我看不出使用这种表示法有什么好处。
template<typename... Args>
void Function(Args... args)
{
}
template<typename... Args>
void Function(Args&&... args)
{
}
Run Code Online (Sandbox Code Playgroud)
我的第一个想法是 && 形式将专门用于 r 值对象,但这个测试证明是错误的:
struct Object
{
// Added bodies so I see what is being called via a step-into
Object() {}
Object(const Object&) {}
Object(Object&&) noexcept {}
Object& operator=(const Object&) { return *this; }
Object& operator=(Object&&) noexcept { return *this; }
};
Object GetObject() { Object o; return o; }
Object obj;
Function(GetObject());
Function(GetObject());
Run Code Online (Sandbox Code Playgroud)
在这里,VS 2017 抱怨该函数的两种形式都是调用的可行候选者。
有人能解释一下这两者之间的区别吗,一个可能比另一个有什么优势?
在以下示例中,对于以下调用,类型推断失败mkPair2:
#include <functional>
template <class A, class B>
struct Pair {
A left; B right;
};
template <class A, class B>
Pair<A,B> mkPair1 (A left, B right) {
return (Pair<A,B>) { left, right };
}
template <class A, class B>
std::function<Pair<A,B>(B)> mkPair2 (A left) {
return [left] (B right) {
return (Pair<A,B>) { left, right };
};
}
Pair<int, char> ex1 = mkPair1 (2, 'a');
Pair<int, char> ex2 = mkPair2 (2) ('a');
Run Code Online (Sandbox Code Playgroud)
问题是mkPair2有两个模板参数,但是调用(2)只提供了其中一个参数,因此编译器立即抛出它并确定程序是不明确的,即使第二种类型可以从下面的('a') …
我看到的代码如下:
template<class Function>
void MyFunc(Function&& function) { function(...); }
Run Code Online (Sandbox Code Playgroud)
&&与仅按值复制函数相比,这里的优势是什么?作为参考,我使用的是 C++14。
考虑我们需要实现一个f带有模板参数的函数T t。该函数不应同时复制t和接受rvalues和lvalues,因此可能有两种实现:
template <class T>
void f(const T& t) { ... }
template <class T>
void f(T&& t) { ... }
Run Code Online (Sandbox Code Playgroud)
如果我们想改变t里面f的值或者需要保留类的值,就得使用第二个版本了。那么根据这个思路,我们何时以及为什么会选择第一个选项?
我在看书时遇到了可变参数模板,并认为实现一个 python 风格的print函数会很酷。
这是代码。
#include <iostream>
#include <string>
#define None " "
template<typename T, typename... Tail>
void print(T head, Tail... tail, const char* end = "\n")
{
std::cout << head << end;
if constexpr (sizeof...(tail) > 0)
{
print(tail..., end);
}
}
int main()
{
// Error: no instance of function template "print" matches the argument list
print("apple", 0, 0.0f, 'c', true);
// Error: no instance of function template "print" matches the argument list
print("apple", 0, …Run Code Online (Sandbox Code Playgroud) 以下原型旨在进行同步打印:
#include <iostream>
#include <string>
#include <sstream>
#include <mutex>
#include <Windows.h> // for OutputDebugString
std::mutex sync_mutex;
template<typename T>
void sync_print_impl(std::ostringstream& str, const T& t)
{
str << t << " ";
}
template<typename ... Args>
void sync_print_impl(std::ostringstream& str, Args ... args)
{
str; // prevents unused variable warning when sync_print is called without arguments
(..., sync_print_impl(str, args));
}
template <typename... Args>
void sync_print(Args... args)
{
std::ostringstream s;
sync_print_impl(s, args...);
{
std::lock_guard<std::mutex> lg(sync_mutex);
std::cout << s.str() << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
简单测试即可: …
我想将一个参数包传递到一个模板方法中,该方法创建一个由另一个模板参数指定的类型的对象的新实例。
最小代码示例:
我的代码实际上使用创建的类型和处理程序执行更多操作
template<typename T, typename... Args>
static bool CreateAndDo(Handler & rHandler, Args.. args)
{
auto pT = T::Create(args...);
rHandler.DoStuff(std::move(pT));
}
Run Code Online (Sandbox Code Playgroud)
简单用法:
Handler tHander;
// the 0 is just an example of an argument
CreateAndDo<ConcreteType>(tHander, 0);
Run Code Online (Sandbox Code Playgroud)
现在我的问题是我的一个论点是std::unique_ptr.
auto pPtr = std::make_unique<ConcreteArg>();
CreateAndDo<ConcreteType>(tHander, std::move(pPtr));
Run Code Online (Sandbox Code Playgroud)
这将无法编译,因为std::unique_ptr必须由CreateAndDoMethod移动。我知道我需要不断移动参数,但我不知道如何使用参数包来做到这一点。
我怎么能做到这一点?