In c++0x, there is a std::static_pointer_cast for std::shared_ptr, but there is no equivalent method for std::weak_ptr. Is this intentional, or an oversight? If an oversight, how would I define an appropriate function?
This ought to do it for you:
template<class T, class U>
std::weak_ptr<T>
static_pointer_cast(std::weak_ptr<U> const& r)
{
return std::static_pointer_cast<T>(std::shared_ptr<U>(r));
}
This will throw an exception if the weak_ptr has expired. If you would rather get a null weak_ptr, then use r.lock() instead.
Howard's version is correct, but in many cases it makes sense to simply pass weakptr.lock() as parameter to std::static_pointer_cast:
std::weak_ptr<A> a = ...;
std::weak_ptr<B> b = std::static_pointer_cast<B>(a.lock());
This syntax explicitly shows what is going on, and makes code easy to read.
The omission is intentional because despite it's name, std::weak_ptr is not a pointer type and does not provide pointer interface (operator ->, operator *, static_pointer_cast, etc.).
Related
I have the following code sample:
void MyClass::Register2(std::string name, std::string email)
{
m_name = std::move(name);
m_email = std::move(email);
}
void MyClass::Register1(std::string name)
{
Register2(std::move(name), "invalid_email");
}
My questions are:
Do I need to use std::move when calling Register2() from Register1()?
Do I need to call std::move() inside Register1()?
If the answer for question 2. is yes, would be possible to have a dedicated operator instead?
For example:
void MyClass::Register2(std::string name, std::string email)
{
m_name <= name; // perform move
m_email <= email; // perform move
}
Do I need to use std::move when calling Register2() from Register1()?
Yes, because name is an lvalue and you want to turn it into an rvalue.
Do I need to call std::move() inside Register1()?
Yes, for the same reason as above.
If the answer for question 2. is yes, would be possible to have a dedicated operator instead?
It would be possible, but I do not think it has been proposed. Also, if it were to be proposed, I do not think it would be accepted as it doesn't bring much value over std::move.
Yes
Yes
No
std::move looks something like this
template<typename T>
std::remove_reference_t<T>&& move(T&& value) {
return static_cast<std::remove_reference_t<T>&&>(value);
}
All it does is it casts the thing you pass as the argument to an rvalue. This step is essential because arguments, even if you pass an rvalue, are always lvalues (because they have names). Lvalues are not moveable, therefore if you don't cast them to an rvalue, move mechanics won't kick in and they will be simply copied.
Operators are functions and there are no exceptions in this case. Special move operator hasn't been proposed and is extremly unlikely to be because it would make the standard longer and more complex (compilers would also be heavily affected) for a feature that saves a couple chars.
I am trying to understand the noexcept feature.
I know it could be confusing, but besides that could noexcept be deduced from the calling function when possible.
This is a non working example of this situation,
void f(){}
void f() noexcept{} // not allowed in c++
void g(){f();} // should call f
void h() noexcept{f();} // should call f noexcept
int main(){
g();
h();
}
If there is no try/catch block in the calling function (h) then the compiler could deduce that one is interested in calling a particular f.
Is this pattern used in some other workaround form?
All I can imagine is somthing like this but it is not very generic:
template<bool NE> void F() noexcept(NE);
template<>
void F<true>() noexcept(true){}
template<>
void F<false>() noexcept(false){}
void g(){F<noexcept(g)>();} // calls F<false>
void h() noexcept{F<noexcept(h)>();} // call F<true>
Some may wonder why that would make sense.
My logic is that that C++ allows to overload with respect to const, both a argument of functions and a member functions.
const member functions prefer to call const member overloads for example.
I think it would make sense for noexcept functions to call noexcept "overloads". Specially if they are not called from a try/catch block.
It makes sense,
Of course it would make sense in principle. One version of the function could run, say, a faster algorithm, but which requires dynamically-allocated extra scratch memory, while the noexcept version could use a slower algorithm with O(1) extra space, on the stack.
but wouldn't be able to resolve the overload ...
As you may know, it's perfectly valid to call noexcept(false) functions from noexcept(true) functions. You're just risking a terminate instead of an exception being thrown; and sometimes - you're not risking anything because you've verified that the inputs you pass cannot trigger an exception. So, how would the compiler know which version of the function you're calling? And the same question for the other direction - maybe you want to call your noexcept(true) function from within a noexcept(false) function? That's also allowed.
... and - it would be mostly syntactic sugar anyway
With C++11, you can write:
#include <stdexcept>
template <bool ne2>
int bar(int x) noexcept(ne2);
template<> int bar<true>(int) noexcept { return 0; }
template<> int bar<false>(int) { throw std::logic_error("error!"); }
and this compiles just fine: GodBolt.
So you can have two function with the same and same arguments, differing only w.r.t. their noexcept value - but with different template arguments.
I don't think overloading on noexcept makes a lot sense on its own. For sure, it makes sense wether your function f is noexcept, especially when called from h, as h needs to catch the possible exception and call std::abort.
However, just overloading on noexcept ain't a good thing to do. It's like disabling exceptions in the standard library. I'm not arguing you shouldn't do that, though, you do loose functionality because of it. For example: std::vector::at throws if the index is invalid. If you disable exceptions, you don't have an alternative for using this functionality.
So if you really want to have 2 versions, you might want to use other alternatives to indicate failure. std::optional, std::expected, std::error_code ...
Even if you manage to overload on noexcept, your function will have a different return type. This ain't something I would expect as a user from your framework.
Hence, I think it's better to overload is a different way, so the user can choose which variant to use, this by using the boolean explicitly, std::nothrow as argument output argument with std::error_code. Or maybe, you should make a choice on the error handling strategy you use in your library and enforce that to your users.
Supposing one needs to obtain a logical value based on a
pack of template parameters, is there a reason to prefer an alias approach
vs a function approach?
Example:
template<bool...> struct bool_pack;
template<bool... bs>
using all_true = std::is_same<bool_pack<bs..., true>,
bool_pack<true, bs...>>;
as opposed to
template<class none=void>
constexpr bool all_true() { return true; }
template<bool First, bool... Rest>
constexpr bool all_true() {
return First and all_true<Rest...>();
}
Time required for compiling your example implementations
... should be measured, of course. That said, I have seen micro-benchmarks where the std::is_same approach leads to significantly shorter compile times; even compared to the C++17 fold expression (true && ... && bs) with the respective compilers. The recursive "function approach" you gave as an example should be clearly inferior in compile-time performance.
Note, however, that one could surely offer the most convenient interface by providing a wrapper around the most "efficient" (regarding compile-time effort) implementation.
Convenience in using the "interface"
Given these two choices, I would prefer the alias approach. If you need the result of that helper as a type (for inheritance, template-metaprogramming with specializations, or for tag dispatch), the alias yields cleaner syntax compared to, say, std::bool_constant<all_true_v<some_condition(), some_other_condition()>()>. In the other direction, it is simple to obtain a value of type bool from the alias: all_true<some_condition(), some_other_condition()>{} (relying on implicit type conversion).
Since C++14, yet another (fancy?) choice is to provide a value by a constexpr variable template which has either type std::true_type or std::false_type. By implicit conversion to bool it can readily be used where plain true or false is required, but it can also be passed as a function argument without losing its compile-time guarantee.
template<bool... bs>
constexpr auto all_true_c = typename std::is_same<
bool_pack<true, bs...>, bool_pack<bs..., true>
>::type{};
It may be a good strategy to follow the naming conventions used in the <type_traits> header of modern C++ providing both forms. If some utility is supposed to provide a value, one finds helper variable templates such as std::is_same_v:
template<class T, class U>
inline constexpr bool is_same_v = is_same<T, U>::value;// (since C++17)
if some helper is supposed to provide a type, one finds helper types such as std::decay_t:
template<class T>
using decay_t = typename decay<T>::type;// (since C++14)
... in addition to the conventional utilities without suffix, respectively.
I have a type A that's designed to be implicitly casted to type B. Here's an example case I'd like to use it in:
// Current implementation:
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b),
[](const A& a) -> B { return a; }); // Thanks, Kerrek SB.
// Ideal implementation - Won't compile, expected '(' after 'static_cast'.
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b),
static_cast<B>);
What can I do to make the latter option compile?
static_cast<B>, while it is invoked with function-call syntax cannot be passed like other callable things. E.g., there's no way to use & to get a function pointer to it.
You can use a short little lambda to achieve something similar to passing a function pointer to static_cast<B>, as you do in your current implementation:
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b),
[](const A& a) -> B { return a; });
Another option--in this particular case--would be to construct a vector<B> from the vector<A>:
std::vector<B> vec_of_b(vec_of_a.begin(), vec_of_a.end());
(This answer is a summary of the comments on both the question and bipll's answer.)
Build a functor enclosing static_cast:
template <typename T>
struct StaticCast
{
template <typename U>
T operator()(const U& rhs)
{
return static_cast<T>(rhs);
}
};
With this, you can call std::transform:
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b), StaticCast<b>());
It can be used in the case the output vector is already defined in place of the lambda shown in comments. If not, prefer the constructor mentioned in another answer**.
This functor version is compliant with C++98 if needed -- even if OP is tagged C++11, it may be worthy to note this point.
** Note that with this particular constructor, a warning C4244 is raised with VS compiler (tested with VS2017).
Yes, that's the way anonymous functions work in C++, and static_cast is not a function so you cannot pass its address as the mapped function. You'll have to deal with it.
You cannot use a constructor either.
Consider a class D derived from a class B, and a sb instance of std::shared_ptr<B>. Once I have verified that dynamic_cast<D*>(sb.get()) is possible, I want to create a proper std::shared_ptr<D> from sb. In other words, I'd like to implement a kind of dynami_cast<> between shared_ptr's. How can I do this in a clean way? A possible solution would be to make B derive from std::enable_shared_from_this and to use shared_from_this() from the (casted) pointer to D. But this would require a change in the definition of type B. Are there better ideas? Is there anything in boost?
Are you aware of std::dynamic_pointer_cast?
http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast
As other answers pointed out, the standard library already provides what you want, but for completeness, implementing it is easy:
template<typename To, typename From>
std::shared_ptr<To>
dynamic_pointer_cast(const std::shared_ptr<From>& from)
{
return std::shared_ptr<To>(from, dynamic_cast<To*>(from.get()));
}
This uses the aliasing constructor to create a new shared_ptr of a different type that shares ownership with from, so they share the same reference count even though they own different pointers (in this case the pointers they own are different types but point to the same object, but that doesn't have to be true.)
This isn't quite right, because if the cast fails (returning a null pointer) you get a shared_ptr that stores a null pointer, but shares ownership with a non-null pointer. To handle that we need a small tweak:
template<typename To, typename From>
std::shared_ptr<To>
dynamic_pointer_cast(const std::shared_ptr<From>& from)
{
if (auto p = dynamic_cast<To*>(from.get()))
return std::shared_ptr<To>(from, p);
return {};
}
Now we return an empty shared_ptr<To> if the cast fails, which is a better match to the behaviour of dynamic_cast<To*>.
Look here: dynamic_pointer_cast