the following are 2 of weak_ptr's constructors:
http://msdn.microsoft.com/en-us/library/bb982126.aspx
weak_ptr(const weak_ptr&);
template<class Other>
weak_ptr(const weak_ptr<Other>&);
actual code (from memory):
weak_ptr(const weak_ptr& _Other)
{ // construct weak_ptr object for resource pointed to by _Other
this->_Resetw(_Other);
}
template<class _Ty2>
weak_ptr(const weak_ptr<_Ty2>& _Other,
typename enable_if<is_convertible<_Ty2 *, _Ty *>::value,
void *>::type * = 0)
{ // construct weak_ptr object for resource pointed to by _Other
this->_Resetw(_Other);
}
Q1: Why is the top copy constructor even there? It looks like the bottom one accounts for every case (including the top one). Does it even get called? and if they didn't include it would the bottom one take it's place?
Q2: What's going on with the second argument of the bottom (templated) constructor. I think I understand the SFINAE aspect, but I don't understand why there is an extra * after ::type
Q1) If you don't write a copy constructor, the compiler will generate one for you, which wouldn't be what you want. Templated conversion constructors don't count.
Q2) Remember that shared_ptr<T> is like a T*, convertibility must be checked at the level of pointers. If T* is convertible to U* then you should be able to assign one to the other. Think of pointers-to-base. [Sorry, that wasn't what you asked.] The final argument type just needs to exist, but also we don't want to have to specify the argument itself. A universal way of making up a type for which we can also provide a default argument is a pointer. In short, we need to make the function depend on a type that may or may not exist, but without actually requiring the user to know about this.
Re Q1: a templated constructor is never a "copy constructor", even if it manages to copy. if there is no user-defined "copy constructor", then the compiler will generate one as needed.
Re Q2: the second argument, a pointer defaulted to 0, is just to have a place to put the enable_if. you can find more about that (if i recall correctly) in the Boost documentation.
Cheers & hth.,
Related
Recently, I've decided to write a class storing a variant with reference_wrapper<const vector> and vector for having a choice either to own the value or having only a reference of it. That is, std::variant<vector<string>, reference_wrapper<const vector<string>>>.
The interesting part is what the variant stores depending on initialization.
I did a small investigation, and it turned out, that in all cases vector<string> type wins, except for the case when passing via std::cref. The same applies to functions (somewhat expected, because constructors are similar to functions in this way)
void f(vector<string>); // #1
void f(reference_wrapper<const vector<string>>); // #2
vector<string> data;
const vector<string>& get_data();
f(data); // #1
f(std::cref(data)) // #2
f(get_data()); // #1
f(std::cref(get_data())) // #2
The question is why the vector<string> has the priority here. I looked at Best viable function section here , but it didn't make much sense. It seems, that
4) or, if not that, F1 is a non-template function while F2 is a template specialization
part chooses vector<string> over reference_wrapper<vector<string>> (because reference_wrapper constructor is templated), but I'm not sure, because I can't fully understand if they are equal using the rule
1) There is at least one argument of F1 whose implicit conversion is better than the corresponding implicit conversion for that argument of F2
Can someone please describe all the implicit conversions applied in each case and show the true reason why one overload is preferred over another? To me, they are as follows:
f(data) = f(vector<string>&) -> (*exact match* implicit conversion) -> f(vector<string>)
f(data) = f(vector<string>&) -> (*conversion* implicit conversion) -> f(reference_wrapper<vector<string>>)
Did I miss something?
Another question, connected to this topic: Ranking of implicit conversion sequences section again,here leaves a question, is T(const T&) considered an Exact match (user-defined conversion of class type to the same class) or Conversion?
First, Although std::reference_wrapper is part of standard library it is treated as user-defined type.
For example an implicit conversion from std::vector & to const std::vector & is always preferred over an implicit conversion from std::vector& to std::reference_wrapper<vector>. That is because (as per standard) the former one is a standard conversion, but the later is a user-defined conversion. the first one is called standard conversion because it adds a const to your type but the second is treated as converting some type to totally different type.
check this code and see cppreference.com.
Second, I'm trying to guess some good alternative. I see you want either to store a reference to vector OR move/(copy as cheap as possible) or (you could say directly initialize) the data inside your class if it is not already stored (safely) in some variable. Maybe you could consider using move semantics. you can play with code here
using TVar = std::variant<reference_wrapper<const vector<string>>, vector<string>>;
class Config {
private:
TVar data;
public:
const vector<string>& get_data() const{
if (data.index() == 1)
return get<1>(data);
else return get<0>(data);
}
Config(const vector<string>& it):data(cref(it)){}
Config(vector<string>&& it):data(move(it)){}
};
Here we have two functions.
One that takes reference to "stored value" (more precisely lvalue). wrapping it in cref so that it causes the reference_wrapper alternative in the variant to be the best overload.
The other does the magic. it is the reference to values that are either written directly (aka pvalues) and values that use the magic std::move function (aka xvalues). if you have never seen this, please reference this respectable Q&A What is move semantics?
catch(...) :), this is it. also notice, you don't need the std::monostate as this is only needed for making the variant default constructible (with no arguments). you can make your class default constructible like this.
Config(vector<string>&& it = {}):data(move(it)){}
There is absolutely no reason to store reference_wrapper whatsoever. Just use a pointer like any sane programmer. reference_wrapper is used to properly trigger std::invoke and associated classes/functions like thread and bind.
I would like to use the optional idiom inside my constexpr function to easily clarify if the variable is set or not.
What I have tried with std::experimental::optional:
constexpr bool call()
{
std::experimental::optional<bool> r;
r = true; // Error
// Similar error with:
// r = std::experimental::optional<bool>(true);
if (!r)
{
return false;
}
return *r;
}
I get the error: call to non-constexpr function - so the assignment is not possible, because this operation cannot be constexpr (Example).
But if I implement my own (very ugly, just for example) optional class, it works, because I don´t implement the assignment operator/constructor explicit.
template<typename T>
struct optional
{
bool m_Set;
T m_Data;
constexpr optional() :
m_Set(false), m_Data{}
{
}
constexpr optional(T p_Data) :
m_Set(true), m_Data(p_Data)
{
}
explicit constexpr operator bool()
{
return m_Set;
}
constexpr T operator *()
{
return m_Data;
}
};
How could I use std::..::optional in the same context with assignment inside constexpr functions?
Basically, you can't. The problem with your simple implementation is that it requires T be default-constructible - if this is not the case, this won't work.
To get around this, most implementation use either a union or some (suitably aligned) storage that can hold a T. If you are passed a T in the constructor, then all well and good, you can initialize this directly (hence it will be constexpr). However, the tradeoff here is that when calling operator=, copying the value across may require a placement-new call, which cannot be constexpr.
For example, from LLVM:
template <class _Up,
class = typename enable_if
<
is_same<typename remove_reference<_Up>::type, value_type>::value &&
is_constructible<value_type, _Up>::value &&
is_assignable<value_type&, _Up>::value
>::type
>
_LIBCPP_INLINE_VISIBILITY
optional&
operator=(_Up&& __v)
{
if (this->__engaged_)
this->__val_ = _VSTD::forward<_Up>(__v);
else
{
// Problem line is below - not engaged -> need to call
// placement new with the value passed in.
::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v));
this->__engaged_ = true;
}
return *this;
}
As for why placement new is not constexpr, see here.
This is not possible, as explained in n3527:
Making optional a literal type
We propose that optional<T> be a literal type for trivially
destructible T's.
constexpr optional<int> oi{5};
static_assert(oi, ""); // ok
static_assert(oi != nullopt, ""); // ok
static_assert(oi == oi, ""); // ok
int array[*oi]; // ok: array of size 5
Making optional<T> a literal-type in general is impossible: the
destructor cannot be trivial because it has to execute an operation
that can be conceptually described as:
~optional() {
if (is_engaged()) destroy_contained_value();
}
It is still possible to make the destructor trivial for T's which
provide a trivial destructor themselves, and we know an efficient
implementation of such optional<T> with compile-time interface —
except for copy constructor and move constructor — is possible.
Therefore we propose that for trivially destructible T's all
optional<T>'s constructors, except for move and copy constructors,
as well as observer functions are constexpr. The sketch of reference
implementation is provided in this proposal.
In other words, it's not possible to assign a value to r even if you mark it as constexpr. You must initialize it in the same line.
How could I use std::..::optional in the same context with assignment
inside constexpr functions?
std::optional is meant to hold a value that may or may not be present. The problem with std::optional's assignment is that it must destroy the old state (call the destructor of the contained object) if any. And you cannot have a constexpr destructor.
Of cause, Trivial and integral types shouldn't have a problem, but I presume the generalization was to keep things sane. However, Assignment could have been made constexpr for trivial types. Hopefully, it will be corrected. Before then, you can role out yours. :-)
Even std::optional's constructor that you think is constexpr, is actually selectively constexpr (depending on whether the selected object constructor is). Its proposal can be found here
Unfortunately, constexpr support in std::optional is somewhat rudimentary; the constexpr-enabled member functions are just the (empty and engaged) constructors, the destructor and some observers, so you cannot alter the engaged state of an optional.
This is because there would be no way to implement assignment for non-trivially copyable types without using placement new and in-place destruction of the contained object, which is illegal within constexpr context. The same currently holds for copy and move constructors, although that may change with guaranteed copy elision, but in any case the standard marks those special member functions as non-constexpr, so you cannot use them in constexpr context.
The fix would be to make the assignment operator conditionally constexpr dependent on whether the contained type is trivial (std::is_trivial_v<T>).
There is some discussion of this issue at the reference implementation; although it's probably too late to get constexpr assignment for trivial optionals into the next version of the Standard, there's nothing preventing you writing your own (e.g. by copying and fixing the reference implementation).
I have a C++ function that takes as arguments something like:
void myFunction(shared_ptr<const MyObject> ptr)) {
...
}
and in my main code I do something like this, and it compiles:
shared_ptr<MyObject> test(new MyObject());
myFunction(test);
Does this mean that inside MyFunction, if I dereference ptr, then the object is constant and cannot be modified?
What are the conversions going on to allow this to compile?
It uses the following constructor of std::shared_ptr:
template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
Which is defined to "not participate in the overload resolution unless Y* is implicitly
convertible to T*". Since, in your example, T* is implicitly convertible to const T*, everything is fine. This is nice, of course, because it means that shared_ptrs behave just like raw pointers.
The code compiles because there is a constructor of shared_ptr<const MyObject> that takes a shared_ptr<MyObject> (shown in Joseph Mansfield's answer), since a const MyObject can be bound without issue to a MyObject (see What is a converting constructor in C++ ? What is it for? and MSDN). Indeed, if you try to modify the value pointed to by ptr in myFunction, then you will get compilation errors indicating that you are trying to modify a constant object.
The function std::move() is defined as
template<typename T>
typename std::remove_reference<T>::type&& move(T && t)
{
return static_cast<typename std::remove_reference<T>::type&&>( t );
}
There are four places where I can imagine the move constructor to be called:
When the parameter is passed.
When the cast is performed.
When the result is returned.
Not in the std::move() function itself but possibly at the place where the returned reference ultimately arrives.
I would bet for number 4, but I'm not 100% sure, so please explain your answer.
There is no move construction going on. std::move() accepts a reference and returns a reference. std::move() is basically just a cast.
Your guess 4. is the right one (assuming that you are actually calling a move constructor in the end).
std::move is just a type cast, it tells the compiler that the type is an rvalue.
This is a follow-on question to
C++0x rvalue references and temporaries
In the previous question, I asked how this code should work:
void f(const std::string &); //less efficient
void f(std::string &&); //more efficient
void g(const char * arg)
{
f(arg);
}
It seems that the move overload should probably be called because of the implicit temporary, and this happens in GCC but not MSVC (or the EDG front-end used in MSVC's Intellisense).
What about this code?
void f(std::string &&); //NB: No const string & overload supplied
void g1(const char * arg)
{
f(arg);
}
void g2(const std::string & arg)
{
f(arg);
}
It seems that, based on the answers to my previous question that function g1 is legal (and is accepted by GCC 4.3-4.5, but not by MSVC). However, GCC and MSVC both reject g2 because of clause 13.3.3.1.4/3, which prohibits lvalues from binding to rvalue ref arguments. I understand the rationale behind this - it is explained in N2831 "Fixing a safety problem with rvalue references". I also think that GCC is probably implementing this clause as intended by the authors of that paper, because the original patch to GCC was written by one of the authors (Doug Gregor).
However, I don't this is quite intuitive. To me, (a) a const string & is conceptually closer to a string && than a const char *, and (b) the compiler could create a temporary string in g2, as if it were written like this:
void g2(const std::string & arg)
{
f(std::string(arg));
}
Indeed, sometimes the copy constructor is considered to be an implicit conversion operator. Syntactically, this is suggested by the form of a copy constructor, and the standard even mentions this specifically in clause 13.3.3.1.2/4, where the copy constructor for derived-base conversions is given a higher conversion rank than other user-defined conversions:
A conversion of an expression of class type to the same class type is given Exact Match rank, and a conversion
of an expression of class type to a base class of that type is given Conversion rank, in spite of the fact that
a copy/move constructor (i.e., a user-defined conversion function) is called for those cases.
(I assume this is used when passing a derived class to a function like void h(Base), which takes a base class by value.)
Motivation
My motivation for asking this is something like the question asked in How to reduce redundant code when adding new c++0x rvalue reference operator overloads ("How to reduce redundant code when adding new c++0x rvalue reference operator overloads").
If you have a function that accepts a number of potentially-moveable arguments, and would move them if it can (e.g. a factory function/constructor: Object create_object(string, vector<string>, string) or the like), and want to move or copy each argument as appropriate, you quickly start writing a lot of code.
If the argument types are movable, then one could just write one version that accepts the arguments by value, as above. But if the arguments are (legacy) non-movable-but-swappable classes a la C++03, and you can't change them, then writing rvalue reference overloads is more efficient.
So if lvalues did bind to rvalues via an implicit copy, then you could write just one overload like create_object(legacy_string &&, legacy_vector<legacy_string> &&, legacy_string &&) and it would more or less work like providing all the combinations of rvalue/lvalue reference overloads - actual arguments that were lvalues would get copied and then bound to the arguments, actual arguments that were rvalues would get directly bound.
Clarification/edit: I realize this is virtually identical to accepting arguments by value for movable types, like C++0x std::string and std::vector (save for the number of times the move constructor is conceptually invoked). However, it is not identical for copyable, but non-movable types, which includes all C++03 classes with explicitly-defined copy constructors. Consider this example:
class legacy_string { legacy_string(const legacy_string &); }; //defined in a header somewhere; not modifiable.
void f(legacy_string s1, legacy_string s2); //A *new* (C++0x) function that wants to move from its arguments where possible, and avoid copying
void g() //A C++0x function as well
{
legacy_string x(/*initialization*/);
legacy_string y(/*initialization*/);
f(std::move(x), std::move(y));
}
If g calls f, then x and y would be copied - I don't see how the compiler can move them. If f were instead declared as taking legacy_string && arguments, it could avoid those copies where the caller explicitly invoked std::move on the arguments. I don't see how these are equivalent.
Questions
My questions are then:
Is this a valid interpretation of the standard? It seems that it's not the conventional or intended one, at any rate.
Does it make intuitive sense?
Is there a problem with this idea that I"m not seeing? It seems like you could get copies being quietly created when that's not exactly expected, but that's the status quo in places in C++03 anyway. Also, it would make some overloads viable when they're currently not, but I don't see it being a problem in practice.
Is this a significant enough improvement that it would be worth making e.g. an experimental patch for GCC?
What about this code?
void f(std::string &&); //NB: No const string & overload supplied
void g2(const std::string & arg)
{
f(arg);
}
...However, GCC and MSVC both reject g2 because of clause 13.3.3.1.4/3, which prohibits lvalues from binding to rvalue ref arguments. I understand the rationale behind this - it is explained in N2831 "Fixing a safety problem with rvalue references". I also think that GCC is probably implementing this clause as intended by the authors of that paper, because the original patch to GCC was written by one of the authors (Doug Gregor)....
No, that's only half of the reason why both compilers reject your code. The other reason is that you can't initialize a reference to non-const with an expression referring to a const object. So, even before N2831 this didn't work. There is simply no need for a conversion because a string is a already a string. It seems you want to use string&& like string. Then, simply write your function f so that it takes a string by value. If you want the compiler to create a temporary copy of a const string lvalue just so you can invoke a function taking a string&&, there wouldn't be a difference between taking the string by value or by rref, would it?
N2831 has little to do with this scenario.
If you have a function that accepts a number of potentially-moveable arguments, and would move them if it can (e.g. a factory function/constructor: Object create_object(string, vector, string) or the like), and want to move or copy each argument as appropriate, you quickly start writing a lot of code.
Not really. Why would you want to write a lot of code? There is little reason to clutter all your code with const&/&& overloads. You can still use a single function with a mix of pass-by-value and pass-by-ref-to-const -- depending on what you want to do with the parameters. As for factories, the idea is to use perfect forwarding:
template<class T, class... Args>
unique_ptr<T> make_unique(Args&&... args)
{
T* ptr = new T(std::forward<Args>(args)...);
return unique_ptr<T>(ptr);
}
...and all is well. A special template argument deduction rule helps differentiating between lvalue and rvalue arguments and std::forward allows you to create expressions with the same "value-ness" as the actual arguments had. So, if you write something like this:
string foo();
int main() {
auto ups = make_unique<string>(foo());
}
the string that foo returned is automatically moved to the heap.
So if lvalues did bind to rvalues via an implicit copy, then you could write just one overload like create_object(legacy_string &&, legacy_vector &&, legacy_string &&) and it would more or less work like providing all the combinations of rvalue/lvalue reference overloads...
Well, and it would be pretty much equivalent to a function taking the parameters by value. No kidding.
Is this a significant enough improvement that it would be worth making e.g. an experimental patch for GCC?
There's no improvement.
I don't quite see your point in this question. If you have a class that is movable, then you just need a T version:
struct A {
T t;
A(T t):t(move(t)) { }
};
And if the class is traditional but has an efficient swap you can write the swap version or you can fallback to the const T& way
struct A {
T t;
A(T t) { swap(this->t, t); }
};
Regarding the swap version, I would rather go with the const T& way instead of that swap. The main advantage of the swap technique is exception safety and is to move the copy closer to the caller so that it can optimize away copies of temporaries. But what do you have to save if you are just constructing the object anyway? And if the constructor is small, the compiler can look into it and can optimize away copies too.
struct A {
T t;
A(T const& t):t(t) { }
};
To me, it doesn't seem right to automatically convert a string lvalue to a rvalue copy of itself just to bind to a rvalue reference. An rvalue reference says it binds to rvalue. But if you try binding to an lvalue of the same type it better fails. Introducing hidden copies to allow that doesn't sound right to me, because when people see a X&& and you pass a X lvalue, I bet most will expect that there is no copy, and that binding is directly, if it works at all. Better fail out straight away so the user can fix his/her code.