给定:
#include <iostream> #include <functional> template<class T> // Just for overloading purposes struct behaviour1 : std::reference_wrapper<T const> { using base_t = std::reference_wrapper<T const>; using base_t::base_t; // This wrapper will never outlive the temporary // if used correctly behaviour1(T&& t) : base_t(t) {} }; template<class T> behaviour1(T&&) -> behaviour1<std::decay_t<T> >; struct os_wrapper : std::reference_wrapper<std::ostream> { using std::reference_wrapper<std::ostream>::reference_wrapper; template<class T> os_wrapper& operator<<(behaviour1<T> const& v) { *this << v.get(); // #1 return *this; } template<class U> os_wrapper& operator<<(U&& t) { this->get() << t; return *this; } }; int main() { os_wrapper(std::cout) << behaviour1(3); }在第 1 行中,是实际执行的间接寻址,考虑到特定用例(立即解包的包装器,也未复制既不绑定到函数参数之外的本地引用),或者编译器是否会检测到该对象是立即展开并仅使用原始对象?否则哪种设计更好(例如,仅保存对象副本的标量类型的部分特化是否会更有效)?
In line #1, is the indirection actually performed, given that specific use case (a wrapper that is inmediatly unwrapped, and nor copied neither bound to local references except function parameters), or will the compiler just detect that the object is inmediatly unwrapped and just use the original object instead? Which will be a better design otherwise (for example, whether a partial specialization for scalar types that just save a copy of the object will be more efficient)?
我对 gcc(版本 7,-O3 -std=c++17)特别感兴趣,尽管我猜 clang和 gcc 执行类似的优化技术.
I'm interested specifically in gcc (version 7, -O3 -std=c++17) although I guess both clang and gcc performs similar optimization techniques.
推荐答案在优化构建中使用 std::reference_wrapper 方法的预期成本为 0,因为所有 std::reference_wrapper 代码可以内联.语句os_wrapper(std::cout)<<<的汇编输出行为1(3);是:
The expected cost of using methods of std::reference_wrapper in an optimized build is 0 because all std::reference_wrapper code can be inlined. The assembly output of statement os_wrapper(std::cout) << behaviour1(3); is:
movl $3, %esi movl std::cout, %edi call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)内联使 Stroustrup 喜欢提到的零开销抽象成为可能.
Inlining is what enables zero-overhead abstractions which Stroustrup likes to mention.
更多推荐
解包 std::reference
发布评论