有没有办法编写一个宏来仅使用变量名(即相当于 std::forward<T>(t) 的 FWD(t))进行完美转发?
Is there a way to write a macro to do perfect forwarding using only the variable name (i.e. a FWD(t) which is equivalent to std::forward<T>(t))?
我有类似的东西(比方说):
template <typename Collection, typename Item>
void foo_collection(Collection&& c, Item && i) {
foo(std::forward<Collection>(c), std::forward<Item>(i));
}
我不喜欢 std::forward<Collection>(c)
太长了。相反,我想这样做:
template <typename Collection, typename Item>
void foo_collection(Collection&& c, Item&& i) {
foo(FWD(c), FWD(i));
}
我想一定有办法使用 decltype
来做到这一点。我想,给定 decltype(i)
,如果我从中删除所有引用和常量,我会得到 Item
,然后它应该可以工作:
#define FWD(v) \
std::forward< \
typename std::remove_const<\
typename std::remove_reference<\
decltype(v)>::type>::type>(v)
然而,这个doesn't work:
void foo(int& a) { cout << "ref" << endl; }
void foo(const int& a) { cout << "cref" << endl; }
template <typename T>
void call_foo(T&& t) { foo(FWD(t)); }
int main() {
int a = 10;
foo(10); // 1) prints cref
foo(a); // 2) prints ref
call_foo(10); // 3) prints cref
call_foo(a); // 4) prints cref
return 0;
}
为什么 4
调用 cref
重载,而不是 ref
重载?
我试过 #define FWD(a) std::forward<decltype(a)>(a)
,在这个例子中是 did work。但是,我猜它不会在所有情况下都有效。是这样吗,如果是这样,它在哪些情况下不起作用?
最后,如果后一种方法不起作用,有没有办法以一种有效的方式编写这个宏?
#define FWD(a) std::forward<decltype(a)>(a)
会起作用的。只要 a
是变量的名称,decltype(a)
就是它被声明为的类型,这就是您应该作为其类型参数传递给 forward
的类型。
如果你传入一个表达式,事情会变得很奇怪。但是,我想不出它会失败的情况。
当然这不适用于 forward
的一些更高级的用途。
方法
#define FWD(a) std::forward<decltype(a)>(a)
实际效果如所见here
void foo(int& a) { cout << "lref" << endl; }
void foo(const int& a) { cout << "cref" << endl; }
void foo(int&& a) { cout << "rref" << endl; }
template <typename T>
void call_foo(T&& t) { foo(FWD(t)); }
int main() {
int a = 10;
call_foo(10); // 3) prints rref
call_foo(a); // 4) prints lref
return 0;
}
我有类似的东西(比方说):
template <typename Collection, typename Item>
void foo_collection(Collection&& c, Item && i) {
foo(std::forward<Collection>(c), std::forward<Item>(i));
}
我不喜欢 std::forward<Collection>(c)
太长了。相反,我想这样做:
template <typename Collection, typename Item>
void foo_collection(Collection&& c, Item&& i) {
foo(FWD(c), FWD(i));
}
我想一定有办法使用 decltype
来做到这一点。我想,给定 decltype(i)
,如果我从中删除所有引用和常量,我会得到 Item
,然后它应该可以工作:
#define FWD(v) \
std::forward< \
typename std::remove_const<\
typename std::remove_reference<\
decltype(v)>::type>::type>(v)
然而,这个doesn't work:
void foo(int& a) { cout << "ref" << endl; }
void foo(const int& a) { cout << "cref" << endl; }
template <typename T>
void call_foo(T&& t) { foo(FWD(t)); }
int main() {
int a = 10;
foo(10); // 1) prints cref
foo(a); // 2) prints ref
call_foo(10); // 3) prints cref
call_foo(a); // 4) prints cref
return 0;
}
为什么 4
调用 cref
重载,而不是 ref
重载?
我试过 #define FWD(a) std::forward<decltype(a)>(a)
,在这个例子中是 did work。但是,我猜它不会在所有情况下都有效。是这样吗,如果是这样,它在哪些情况下不起作用?
最后,如果后一种方法不起作用,有没有办法以一种有效的方式编写这个宏?
#define FWD(a) std::forward<decltype(a)>(a)
会起作用的。只要 a
是变量的名称,decltype(a)
就是它被声明为的类型,这就是您应该作为其类型参数传递给 forward
的类型。
如果你传入一个表达式,事情会变得很奇怪。但是,我想不出它会失败的情况。
当然这不适用于 forward
的一些更高级的用途。
方法
#define FWD(a) std::forward<decltype(a)>(a)
实际效果如所见here
void foo(int& a) { cout << "lref" << endl; }
void foo(const int& a) { cout << "cref" << endl; }
void foo(int&& a) { cout << "rref" << endl; }
template <typename T>
void call_foo(T&& t) { foo(FWD(t)); }
int main() {
int a = 10;
call_foo(10); // 3) prints rref
call_foo(a); // 4) prints lref
return 0;
}