有没有办法编写一个宏来仅使用变量名(即相当于 std::forward<T>(t) 的 FWD(t) )进行完美转发?

Cla*_*diu 2 c++ templates decltype perfect-forwarding c++11

我有类似的东西(比方说):

template <typename Collection, typename Item>
void foo_collection(Collection&& c, Item && i) {
    foo(std::forward<Collection>(c), std::forward<Item>(i));
}
Run Code Online (Sandbox Code Playgroud)

std::forward<Collection>(c)我不喜欢这么长的事实。我想这样做:

template <typename Collection, typename Item>
void foo_collection(Collection&& c, Item&& i) {
    foo(FWD(c), FWD(i));
}
Run Code Online (Sandbox Code Playgroud)

我认为必须有一种方法可以使用decltype. 我想,给定decltype(i),如果我从中删除所有引用和常量,我会得到Item,然后它应该可以工作:

#define FWD(v) \
    std::forward< \
        typename std::remove_const<\
        typename std::remove_reference<\
        decltype(v)>::type>::type>(v)
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用

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;
}
Run Code Online (Sandbox Code Playgroud)

为什么4cref重载,而不叫ref重载?

我尝试过#define FWD(a) std::forward<decltype(a)>(a),在这个例子中它确实有效。但是,我猜它不会在所有情况下都有效。是这样吗?如果是这样,它在哪些情况下不起作用?

最后,如果后一种方法不起作用,有没有什么方法可以以有效的方式编写这个宏?

Yak*_*ont 5

#define FWD(a) std::forward<decltype(a)>(a)
Run Code Online (Sandbox Code Playgroud)

将工作。只要a是变量的名称,decltype(a)就是它声明的类型,这就是您应该forward作为其类型参数传递的内容。

如果你传递一个表达式,事情可能会变得奇怪。然而,我想不出一个失败的例子。

当然,这对于 的一些更高级的用途不起作用forward