With side-project on Envoy, found something interesting thus jot down for future reference.
- Idiom:
Functions take values as arguments and std::move to final destination. (Less constructor/destructor calls involved)
Or use template trick to limit the universal constructor having higher priority then non-template ones. - C++17 has RVO into the language. Thus,
-fno-elide-constructors
will not turn off RVO in any how. - is_convertible, used as the guard for universal constructor to allow copy constructor takes itself type's instance or derived one.
However, is_convertible isn't using the 'cast' as implementation, which is in run-time, it simply uses a form like:
To test() { return std::declval<From>(); } // ODR use of declval here, which static_assert fails. It's just an example.
That is to say, any type with conversion operator would meet the is_convertible requirement, not only the derived ones. - explicit is your friend. Single parameter constructor, including template ones, use explicit prevent automatic type conversion by accident.
As usual, one example explains what mentioned above.
#include <boost/type_index.hpp>
#include <iostream>
#include <string_view>
#include <utility>
using namespace std;
struct Base {
// -- 1
// Guarded , using enable_if_t, is_convertible_v for C++17
template <typename T, typename = typename enable_if<
!is_convertible<T, Base>::value>::type>
explicit Base(T &&t)
{
}
Base(const Base &) {} // on purpose, compiler generates by default -- 2
Base(Base &&) {} // on purpose, compiler generates by default. -- 3
};
struct Derived : Base {
using Base::Base;
};
struct Mutation {
explicit operator Base()
{
return Base{42}; // Hits (1)
}
};
int main()
{
auto _ = "Pikachu"sv;
Mutation m;
// static_cast<Base>(m); // Can't call this way due to Base's universal
// constructor installed.
Base b1{
m.operator Base()}; // -fno-elide-constructors has no effect for C++17
// By default Move constructor will never be hit in C++17
// Prior then C++17, Move constructor will be hit if no -fno-elide-constructors
Base b2{D{42}}; // Hits (3), no RVO, RVO only happens on _same_ type.
}
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.