Is there a way to move CComBSTR object to std::vector without copying the underlying string? It seems the following code doesn't work.
CComBSTR str(L"SomeStr");
std::vector<CComBSTR> vStr;
vStr.push_back((CComBSTR)str.Detach());
Your code doesn't work because Detach gives you a BSTR, not a CComBSTR. You could have used std::vector<BSTR> vStr, as long as you realise that BSTR points to the first character of the string, but there's also a length prefix before the memory it points to (see, e.g. BSTR (Automation)), so you'd need to be careful with managing it.
Alternatively, you could have used
CComBSTR str(L"SomeStr");
std::vector<CComBSTR> vStr;
vStr.push_back(str);
which would make a copy of the string.
The MSDN page on CComBSTR does not indicate it has any move-semantics, but it might have been added to the code without the documentation being updated.
I don't think so though, in which case your std::move solution in your answer will be the same as my second example: a simple copy.
I've done some experiment and seems the latest CComBSTR supports move semantics so it can be written as:
CComBSTR str(L"SomeStr");
std::vector<CComBSTR> vStr;
vStr.push_back(std::move(str));
Related
Suppose I need to write a function which might take either a constant reference to an lvalue or a temporary value, is there any advantage in terms of performance in writing both overloads, the one taking a const T& and one taking T&&, if we do not want to move from the rvalue?
I was assuming having two overloads (or just writing the function once with universal references) would be beneficial but I can't pin down the exact reason. I even tried a small example: https://godbolt.org/z/53r34x4Mj but I can't really make sense of the generated code.
If you're never going to move from the argument under any circumstance, nor modify it, there is no benefit to writing the version that takes an r-value reference; the const type& version will accept r-values just fine (keeping them alive until the function returns) with no additional overhead.
The only reason to write both versions is if you plan to potentially modify or move-from the argument only when receiving an r-value reference, where the const reference case never does so, and doesn't copy either, because if it would need to copy anyway, you may as well just accept by value and get the best of all worlds (construct directly into argument for prvalues, move construct for xvalues, and copy for everything else, but without hand-writing the code to handle that).
I have been using c++11 for some time but I always avoided using std::move because I was scared that, while reading a library where the user does not have the access to the code, it would try to use the variable after I move it.
So basically something like
void loadData(std::string&& path);
Would not be enough to make the user understand that it will be moved.
Is it expected that the use of && would imply that the data will be moved. I know that comments can be used to explain the use case, but a lot of people dont pay attention to that.
Is it safe to assume that when you see a && the data will be moved, or when should I use std::move and how to make it explicit from the signature.
Is it expected that the use of && would imply that the data will be moved.
Generally speaking yes. A user cannot call loadData with an lvalue. They must provide a prvalue or an xvalue. So if you have a variable to pass, your code would generally look like loadData(std::move(variable)), which is a pretty good indicator of what you're doing from your side. forwarding could also be employed, but you'd still see it at the call site.
Indeed, generally speaking it is extremely rude to move from a parameter which is not an rvalue reference.
I know that std::vector<T>::push_back() has move semantics support. So, when I add a named temporary instance to a vector, I can use std::move().
What are the other common places in the STL that I should grow the habit to add std::move()
I know that std::vector<T>::push_back() has move semantics support.
The support that push_back has is simply an additional overload that takes an rvalue reference, so that the new value T inside the vector can be constructed by invoking T(T&&) instead of T(const T&). The advantage is that the former can be implemented way more efficiently because it assumes that the passed rvalue reference is never going to be used afterwards.
Most Standard Library containers have added similar overloads to their push/enqueue/insert member functions. Additionally, the concept of emplacement has been added (e.g. std::vector<T>::emplace_back), where the values are constructed in place inside the container in order to avoid unnecessary temporaries. Emplacement should be preferred to insertion/pushing.
So, when I add a named temporary instance to a vector, I can use std::move().
"Named temporary" doesn't really make much sense. The idea is that you have an lvalue you don't care about anymore, and you want to turn it into a temporary by using std::move. Example:
Foo foo;
some_vector.emplace_back(std::move(foo));
// I'm sure `foo` won't be used from now on
Just remember that std::move is not special: it literally means static_cast<T&&>.
What are the other common places in the STL that I should grow the habit to add std::move?
This is a really broad question - you should add std::move everywhere it makes sense, not just in the context of the Standard Library. If you have a lvalue you know you're not going to use anymore in a particular code path, and you want to pass it/store it somewhere, then std::move it.
I'm looking at a piece of very old VB6, and have come across usages such as
Form5!ProgressBar.Max = time_max
and
Form5!ProgressBar.Value = current_time
Perusing the answer to this question here and reading this page here, I deduce that these things mean the same as
Form5.ProgressBar.Max = time_max
Form5.ProgressBar.Value = current_time
but it isn't at all clear that this is the case. Can anyone confirm or deny this, and/or point me at an explanation in words of one syllable?
Yes, Form5!ProgressBar is almost exactly equivalent to Form5.ProgressBar
As far as I can remember there is one difference: the behaviour if the Form5 object does not have a ProgressBar member (i.e. the form does not have a control called ProgressBar). The dot-notation is checked at compile time but the exclamation-mark notation is checked at run time.
Form5.ProgressBar will not compile.
Form5!ProgressBar will compile but will give an error at runtime.
IMHO the dot notation is preferred in VB6, especially when accessing controls. The exclamation mark is only supported for backward-compatibility with very old versions of VB.
The default member of a Form is (indirectly) the Controls collection.
The bang (!) syntax is used for collection access in VB, and in many cases the compiler makes use of it to early bind things that otherwise would be accessed more slowly through late binding.
Far from deprecated, it is often preferable.
However in this case since the default member of Form objects is [_Default] As Object containing a reference to a Controls As Object instance, there is no particular advantage or disadvantage to this syntax over:
Form5("ProgressBar").Value
I agree that in this case however it is better to more directly access the control as a member of the Form as in:
Form5.ProgressBar.Value
Knowing the difference between these is a matter of actually knowing VB. It isn't simply syntactic though, the two "paths" do different things that get to the same result.
Hopefully this answer offers an explanation rather merely invoking voodoo.
I need to convert a CString instance into a properly allocated BSTR and pass that BSTR into a COM method. To have code that compiles and works indentically for both ANSI and Unicode I use CString::AllocSysString() to convert whatever format CString to a Unicode BSTR.
Since noone owns the returned BSTR I need to take care of it and release it after the call is done in the most exception-safe manner posible and with as little code as possible.
Currently I use ATL::CComBSTR for lifetime management:
ATL::CComBSTR converted;
converted.Attach( sourceString.AllocSysString() ); //simply attaches to BSTR, doesn't reallocate it
interface->CallMethod( converted );
what I don't like here is that I need two separate statements to just construct the ATL::CComBSTR bound to the convertion result.
Is there a better way to accomplish the same task?
CComBSTR has overloaded constructors for both char* and wchar_t*, which make the call to SysAllocString() on your behalf. So the explicit allocation in your code snippet is actually unnecessary. The following would work just as well:
ATL::CComBSTR converted = sourceString;
interface->CallMethod(converted);
Furthermore, if you have no need to use the converted BSTR elsewhere in your code, you can perform the object construction in-place in the method call, like so:
interface->CallMethod(ATL::CComBSTR(sourceString));
The same applies to the _bstr_t class, which can be used instead of CComBSTR if you don't want a dependency on the ATL.
One of the confusing aspects of Windows programming is managing the conversion of Visual Basic style strings to/from C language style strings. It isn't that it is so difficult, it is just difficult to remember the details. It is usually not done often, and the MSDN documentation is so voluminous that it is difficult to find answers to your questions. But, the worst part is that you could perform some typecast that compiles fine, but doesn't work the way you expect. This results in code that doesn't work, and the bugs are hard to track down. After some experience, you learn to make sure your string conversions are doing what you expect.
C strings are arrays of characters terminated by a NULL character. Visual Basic strings differ in that the length of the string precede the characters in the string. So, a VB string knows its own length. In addition, all VB strings are Unicode (16 bits per character).
String Types
BSTR/C String conversions are required if:
You are doing COM programming in C/C++
You are writing multiple language applications, such as C++ DLL's accessed by Visual Basic applications.
One of _bstr_t constructors allows you to simply attach to existing BSTR so that you can have the exception that you want from CString::AllocSysString when BSTR allocation fails.
// _bstr_t simply attaches to BSTR, doesn't reallocate it
interface->CallMethod( _bstr_t(sourceString.AllocSysString(), false) );
The _bstr_t constructor documentation says:
_bstr_t(
BSTR bstr,
bool fCopy
);
fCopy
If false, the bstr argument is attached to the new object without making a copy by calling SysAllocString.
On the other hand, CComBSTR constructor doesn't seem to have the corresponding signature; although it can be used as well if BSTR allocation failure exception is not really needed, as mentioned by Phil Booth in his answer.