Posts

Showing posts with the label language-lawyer

Why is unique_ptr not equality_comparable_with nullptr_t in C++20?

46 4 Working with C++20's concept s I noticed that std::unique_ptr appears to fail to satisfy the std::equality_comparable_with<std::nullptr_t,...> concept. From std::unique_ptr 's definition, it is supposed to implement the following when in C++20: template<class T1, class D1, class T2, class D2> bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T, class D> bool operator==(const unique_ptr<T, D>& x, std::nullptr_t) noexcept; This requirement should implement symmetric comparison with nullptr -- which from my understanding is sufficient for satisfying equality_comparable_with . Curiously, this issue appears to be consistent on all the major compilers. The following c...

Why does “&& true” added to a constraint make a function template a better overload?

26 1 Consider the following two overloads of a function template foo : template <typename T> void foo(T) requires std::integral<T> { std::cout << "foo requires integral\n"; } template <typename T> int foo(T) requires std::integral<T> && true { std::cout << "foo requires integral and true\n"; return 0; } Note the difference between the two constraints: the second has an extra && true . Intuitively speaking, true is redundant in a conjunction (since X && true is just X ). However, it looks like this makes a semantic difference, as foo(42) would call the second overload. Why is this the case? Specifically, why is the second function template a better overload? ...

Can a primitive-type data member of a derived class be used as a parameter to its base constructor?

14 2 Inspired by my (currently deleted) answer to this question (but there's a summary in my comment thereto), I was wondering whether the constructor for the Derived class in the code below exhibits undefined behaviour. #include <iostream> class Base { public: Base(int test) { std::cout << "Base constructor, test: " << test << std::endl; } }; class Derived : public Base { private: int variable; public: Derived() : Base(variable = 50) { // Is this undefined behaviour? } }; int main() { Derived derived; return 0; } I know that, when the base c'tor is called, the derived object has not yet (formally) been constructed, so the lifetime of the variable member has not yet started. However, this e...

reinterpret_cast bug or UB? [duplicate]

This question already has an answer here: Observing weird behavior with 'auto' and std::minmax 1 answer structured bindings with std::minmax and rvalues 2 answers Consider following code: #include <cstdint> #include <algorithm> std::uintptr_t minPointer(void *first, void *second) { const auto pair = std::minmax( reinterpret_cast<std::uintptr_t>(first), reinterpret_cast<std::uintptr_t>(second) ); return pair.first; } and the assembly generated by GCC8 with -O3 on https://godbolt.org/z/qWJuV_ for minPointer: minPointer(void*, void*): mov rax, QWORD PTR [rsp-8] ret which clearly does not do what is intended by the code creator. Is this code causing some UB or is it GCC(8) bug? This is UB, but not for the reason you might think. The relevant signature o...

Is std::string guaranteed not to give back memory spontaneously?

Is it guaranteed by the standard that std::string will not give back allocated memory spontaneously if reassigned from a string of a smaller size? In other words: std::string str = "Some quite long string, which needs a lot of memory"; str = ""; str = "A new quite long but smaller string"; // Guaranteed to not result in a heap allocation? I ask because i'm depending on this to avoid heap fragmentation. No guarantee whatsoever. [string.cons]/36 defines assigning a const char* to an std::string in term of a move-assignment, whose definition is: [string.cons]/32 basic_string& operator=(basic_string&& str) noexcept(/*...*/) Effects: Move assigns as a sequence container, except that iterators, pointers and references may be invalidated. This shows that the Committee let the implementation choose freely between an invalidating operation and a more conservative one. CPP reference states that assignment to a pointer-to-char Repla...

Destructor of typedef alias

#include <iostream> struct A { ~A(); }; A::~A() { std::cout << "Destructor was called!" << std::endl; } typedef A AB; int main() { AB x; x.AB::~AB(); // Why does this work? x.AB::~A(); } The output of the above program is: Destructor was called! Destructor was called! Destructor was called! I assume the first two lines belonging to user destructor calls, while the third line is due to the destructor being called when exiting the scope of main function. From my understanding a typedef is an alias for a type. In this case AB is an alias for A. Why does this apply for the name of the destructor too? A reference to the language specification is very much appreciated. Edit: This was compiled using Apple LLVM version 9.1.0 (clang-902.0.39.1) on macOS High Sierra Version 10.13.3. Why does this apply for the name of the destructor too? Because standard says: [class.dtor] In an explicit destructor call, the destructor is specified by a ~ ...

Is storage for the same content string literals guaranteed to be the same?

Is the code below safe? It might be tempting to write code akin to this: #include <map> const std::map<const char*, int> m = { {"text1", 1}, {"text2", 2} }; int main () { volatile const auto a = m.at("text1"); return 0; } The map is intended to be used with string literals only. I think it's perfectly legal and seems to be working, however I never saw a guarantee that the pointer for the literal used in two different places to be the same. I couldn't manage to make compiler generate two separate pointers for literals with the same content, so I started to wonder how firm the assumption is. I am only interested whether the literals with same content can have different pointers. Or more formally, can the code above except? I know that there's a way to write code to be sure it works, and I think above approach is dangerous because compiler could decide to assign two different storages for the literal, especially if they...

What's the meaning of “reserved for any use”?

NOTE: This is a c question, though I added c++ in case some C++ expert can provide a rationale or historical reason why C++ is using a different wording than C. In the C standard library specification, we have this normative text, C17 7.1.3 Reserved identifiers (emphasis mine): All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use. All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces. Now I keep reading answers on SO by various esteemed C experts, where they claim it is fine for a compiler or standard library to use identifiers with underscore + uppercase, or double underscore. Doesn't "reserved for any use" mean reserved for anyone except future extensions to the C language itself? Meaning that the implementation is not allowed to use them. While the second phrase above, regarding single leading ...

Why is the destructor called for an object that is not deleted?

struct A { ~A() = delete; }; int main() { new A{}; } This fails to compile with error message: error: use of deleted function 'A::~A()' new A{}; As I understand I'm not destroying the object so why is it trying to call the destructor? Compiled with GCC 8.1.0 g++ -std=c++17 -O2 This is gcc bug 57082. Let's go from the bottom up. [dcl.fct.def.delete]/2: A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed. Clearly, we're not referring to ~A() explicitly. Are we referring to it implicitly? [class.dtor]/12: A destructor is invoked implicitly for a constructed object with static storage duration ([basic.stc.static]) at program termination ([basic.start.term]), for a constructed object with thread storage duration ([basic.stc.thread]) at thread exit, for a constructed object with automatic storage duration ([basic.stc.auto]) when the block in which an object is created exi...

Is double-braced scalar initialization allowed by the C++ standard?

I have the following code: int x = {{}}; Is this syntax valid according to the C++ standard? (I'm interested in C++11 and later.) When using the latest compilers there is no problem, however in some older ones (e.g. GCC 4.8.5) it gives following error: error: braces around scalar initializer for type 'int' This is ill-formed. gcc is wrong to accept it and clang seems to allow it as an extension, as it warns about it. I'm going to quote the latest draft, but it doesn't make a difference. List initialization works as follows as per [dcl.init.list], where T is int in this case: If the initializer list is a designated initializer list, [...] => it's not If T is an aggregate class [...] => it's not If T is a character array [...] => it's not. If T is an aggregate [...] => it's not (only arrays and classes are aggregates) If the initializer list has no elements [...] => it doesn't If T is a specialization of std::initializer_list ...

Pimpl - Why can make_unique be called on an incomplete type

Why does the make_unique call compile? Doesn't make_unqiue require its template argument to be a complete type ? struct F; int main() { std::make_unique<F>(); } struct F {}; The question orignated from my "problem" with my PIMPL implementation: I do understand why the destructor has to be user declared and defined inside the cpp file for the Implementation class (PIMPL). But moving the constructor of the class containing the pimpl- still compiles. class Object {}; class CachedObjectFactory { public: CachedObjectFactory(); ~CachedObjectFactory(); std::shared_ptr<Object> create(int id) const; private: struct CacheImpl; std::unique_ptr<CacheImpl> pImpl; }; Now the cpp file: // constructor with make_unique on incompete type ? CachedObjectFactory::CachedObjectFactory() : pImpl(std::make_unique<CacheImpl>()) {} struct CachedObjectFactory::CacheImpl { std::map<int, std::shared_ptr<Object>> idToObjects; }; //deferred destructor ...

Is main a valid Java identifier?

One of my kids is taking Java in high school and had this on one of his tests: Which of the following is a valid identifier in Java? a. 123java b. main c. java1234 d. {abce e. )whoot He answered b and got it wrong. I looked at the question and argued that main is a valid identifier and that it should have been right. We took a look at the Java spec for identifiers and it reinforced that point. We also wrote a sample program that had a variable called main, as well as a method. He created a written rebuttal that included the Java documentation reference, the test program and the teacher ignored it and says the answer is still incorrect. Is the main a valid identifier? public class J { public static void main(String[] args) { String main = "The character sequence \"main\" is an identifier, not a keyword or reserved word."; System.out.println(main); } } This compiles, and when executed, emits thi...

Why can const char* const & = “hello” compile?

I am reading a code snippet from a book and find this: const char* const & a = "hello"; //can compile const char*& a = "hello"; //cannot All I know is that when initializing a reference, the array to pointer conversion would not take place. const char* const &, a reference to a const pointer, the pointer points to const char. const char*&, a reference to a pointer, the pointer points to const char. So why does adding an extra const, indicating that the pointer is a const, allow it to compile? It's essentially adhering to this formula T const & a = something_convertible_to_T; Where T is const char*. In the first case, a temporary pointer can be materialized, assigned the address of the literal, and then have itself bound to the reference. In the second case, since the lvalue reference isn't const, it can't happen. Another example of more of the same const char* && a = "hello"; // rvalue ref makes a no into a yes....

Confusion about array initialization in C

In C language, if initialize an array like this: int a[5] = {1,2}; then all the elements of the array that are not initialized explicitly will be initialized implicitly with zeroes. But, if I initialize an array like this: int a[5]={a[2]=1}; printf("%d %d %d %d %d\n", a[0], a[1],a[2], a[3], a[4]); output: 1 0 1 0 0 I don't understand, why does a[0] print 1 instead of 0? Is it undefined behaviour? Note: This question was asked in an interview. TL;DR: I don't think the behavior of int a[5]={a[2]=1}; is well defined, at least in C99. The funny part is that the only bit that makes sense to me is the part you're asking about: a[0] is set to 1 because the assignment operator returns the value that was assigned. It's everything else that's unclear. If the code had been int a[5] = { [2] = 1 }, everything would've been easy: That's a designated initializer setting a[2] to 1 and everything else to 0. But with { a[2] = 1 } we have ...