u/memset_0
memset_0
memset_0
Oh no, they are very different. auto is only a compile-time construct that directs the compiler to deduce a type from the available information. It saves typing and good for maintainability:
//These 2 statements compile to the same instructions
auto i = 10; //i is int
int i = 10;
//another example
auto foo() { return 10LL; } //foo returns int64_t
std::any is a standard library class that can contain any type of object. It is not a compiler feature.
memset_0
I see. So std::variant — like a union — requires a member to be an object (region of storage).
I would add this use case in the article. Thank you so much.
memset_0
Thank You!
memset_0
Sounds interesting. Can you please explain that for the benefit of everyone here? thx.
memset_0
I wish for Sockets and IO Event-Loop support at least.
What's the news flash?
memset_0
You can check out folly. It is cross platform now.
Hope C++ standard library has networking support someday.
memset_0
yes, from what i gather.
memset_0
I did not say or imply that the language should make an exception for std::move. I asked why taking the address of an xvalue is an error (std::move is the most common way to create an xvalue expression).
memset_0
This question is about getting deep into the language semantics. There is no need to oversimplify it.
std::move(x) expression is not a temporary. The reason we have std::move is to in fact explicitly tell the compiler that we want to move an lvalue. Temporaries are already movable. And, std::move does not turn an lvalue to a temporary, or move it to a different location or register.
memset_0
Your point about local variable is good.
But ‘x’ is not an xvalue in your example. it has a name. Also, it is a universal or forwarding reference, not even an rvalue reference.
https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
memset_0
std::move(x) is an xvalue. so its both, an rvalue and a glvalue.
memset_0
thats what i thought. but i was hoping someone would cite a source for this reasoning. thx.
memset_0
yes. but it is a glvalue too. depends on how we look at it.
memset_0
Yeah, but my question is why is it disallowed. Why &std::move(x) is invalid when x is an lvalue.
memset_0
“The most important source of xvalues are temporary objects.”
But temporary objects are already movable (prvalues), why would they be most important source of xvalues?
string foo(); // returns temporary
string s;
s = move(foo()); //not good. why would anyone do that when foo() is already movable.
Shouldn’t the only source of xvalues be lvalues:
string c; //lvalue
string m;
m = move(c); // ok
memset_0
Because the article is not about capturing this pointer per se. It is about capturing the current object, which, conceptually, can be captured by reference [this] or by value [*this]. Therefore, *this signifies the current object, and &(*this) reference to it.
memset_0
At this point, some historic background is helpful. The
thiskeyword was introduced to C++ before references. At the time, C++ was translated into C, and the simple pointer semantics ofthiswere convenient. If the entire feature set of references, value categories and classes had been designed together,thiswould have been an lvalue designating the object, and not a prvalue designating the address of the object. We can adopt this historic perspective by thinking of the fundamental object as “*this” rather thanthis.
memset_0
If you created the object without using smart pointer and then in a method you use shared_from_this() you will end with UB
It is no longer UB; since C++17 it is bad_weak_ptr exception.
The only advantage of a static factory method with private/protected constructors is that it avoids the unintended bad_weak_ptr by forcing the object construction through shared_ptr. IMO, that safety comes at a big cost. As shown in the article, you can not use make_shared with private/protected constructors. Also, further extensions or inheritance of the class is tricky and requires significant changes to the custom code. Not to mention the maintenance of the customized code.
memset_0
Thank you for pointing out that the code does not handle Service::getConnection failure. The code in the article would be fixed to handle the possible null 'cp'. The purpose of the article is to only show a concept, however, I agree that it should be explicitly mentioned that a unique_ptr or a custom RAII-guard might be a preferable approach.
memset_0
Correct. make_shared constructs the managed object within the control block. When the ref count reaches zero, the object’s destructor is called but the memory (which is part of the control block) is not freed until the control block itself is destroyed when the weak count also reaches zero. These are the reasons for which the knowledge of shared_ptr internals is very important.
memset_0
Aliases do obscure the type, but IMO the benefits outweigh the pain. Aliases do make the code far more maintainable. And with any good IDE, jumping to or peeking at the declaration of the alias is very quick. As for the maintainability argument, here is an example:
No Alias:
//std::unique_ptr<Foo, Deleter> used at many places:
std::vector<std::unique_ptr<Foo, Deleter>> vec;
std::unique_ptr<Foo, Deleter> p;
void fun(std::unique_ptr<Foo, Deleter>& p);
//more functions and types
Imagine changing the type of deleter from Deleter to Deleter2 in the above scenario. You might have to change potentially at 100s of places.
Alias:
using FooPtr = std::unique_ptr<Foo, Deleter>;
std::vector<FooPtr> vec;
FooPtr p;
void fun(FooPtr& p);
//more places
Changing the type of FooPtr's deleter to Deleter2 is just one line change now.
memset_0
Providing enough of everything and not too much: Productivity, Performance, Portability, and Safety.
memset_0
I have used a few of them. Ignoring cost and considering only features, this is my preference-order:
- Visual Studio
- CLion
- Visual Studio Code
- Emacs
memset_0
The generic parameters (e.g., Integer for ArrayList<Integer>) are type erased by the compiler; that means the parameters are replaced by Object and appropriate type casts are applied. Therefore, the primitive parameters are not supported by Generics. From Type Erasure:
Generics were introduced to the Java language to provide tighter type checks at compile time and to support generic programming. To implement generics, the Java compiler applies type erasure to:
- Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
- Insert type casts if necessary to preserve type safety.
- Generate bridge methods to preserve polymorphism in extended generic types.
Type erasure ensures that no new classes are created for parameterized types; consequently, generics incur no runtime overhead.
Just to elaborate a little that std::any does not have compile-time type-safety. It does have run-time type check.