Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
627 views
in Technique[技术] by (71.8m points)

c++ - is any difference between std::forward<T> and std::forward<decltype(t)>?

are these functions equivalent?

template <class T>
void foo(T && t)
{
    bar(std::forward<T>(t));
}

template <class T>
void foo2(T && t)
{
    bar(std::forward<decltype(t)>(t));
}

template <class T>
void foo3(T && t)
{
    bar(std::forward(t));
}

if they are, can I always use this macro for perfect forwarding?

#define MY_FORWARD(var) std::forward<decltype(var)>(var)

or just use

bar(std::forward(t));

I believe foo2 and foo3 are same, but I found people are always use forward like foo, is any reason to explicitly write the type?

I understand that T and T&& are two different types, but I think std::forward<T> and std::forward<T&&> always give the same result?


Edit:

the reason I want to use macro is I want to save some typing on following C++1y code, I have many similar code in different places

#define XLC_FORWARD_CAPTURE(var) var(std::forward<decltype(var)>(var))
#define XLC_MOVE_CAPTURE(var) var(std::move(var))

template <class T, class U>
auto foo(T && func, U && para )
{
    auto val = // some calculation
    return [XLC_FORWARD_CAPTURE(func),
            XLC_FORWARD_CAPTURE(para),
            XLC_MOVE_CAPTURE(val)](){
              // some code use val
              func(std::forward<U>(para)); 
          };
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Are these functions two equivalent?

Yes, they are equivalent. decltype(t) is the same as T&&, and when used with std::forward, there is no difference between T and T&&, regardless what T is.

Can I always use this macro for perfect forwarding?

Yes, you can. If you want to make your code unreadable and unmaintainable, then do so. But I strongly advise against it. On the one hand, you gain basically nothing from using this macro. And on the other hand, other developers have to take a look at the definition to understand it, and it can result in subtle errors. For example adding additional parentheses won't work:

MY_FORWARD((t))

In contrast, the form with decltype is perfectly valid. In particular, it is the preferred way of forwarding parameters from generic lambda expressions, because there are no explicit type parameters:

[](auto&& t) { foobar(std::forward<decltype(t)>(t)); }

I ignored the 3rd variant with std::forward(t), because it isn't valid.


Update: Regarding your example: You can use call-by-value instead of call-by-reference for the function template foo. Then you can use std::move instead of std::forward. This adds two additional moves to the code, but no additional copy operations. On the other hand, the code becomes much cleaner:

template <class T, class U>
auto foo(T func, U para)
{
    auto val = // some calculation
    return [func=std::move(func),para=std::move(para),val=std::move(val)] {
        // some code use val
        func(std::move(para)); 
    };
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...