Is address of global variable constexpr? - c++11

Consider following
struct dummy{};
dummy d1;
dummy d2;
template<dummy* dum>
void foo()
{
if (dum == &d1)
; // do something
else if (dum == &d2)
; // do something else
}
Now, it is possible to call foo like this
foo<&d1>();
foo<&d2>();
and everything works as expected. But following does not
constexpr dummy* dum_ptr = &d1;
foo<dum_ptr>();
With this error from Visual studio
error C2975: dum_ptr: invalid template argument for foo, expected compile-time constant expression
While this works
constexpr dummy& dum_ref = d1;
foo<&dum_ptr>();
In visual studio, but not in G++, because of
note: template argument deduction/substitution failed:
error: & dum_ref is not a valid template argument for dummy* because it is not the address of a variable
foo<&dum_ref>();
EDIT:
Since C++17, std::addressof is being marked as constexpr, so I would guess it should work.

GCC is right on this one.
The expressions are definitely constant-expressions*, since they are assigned to a constexpr variable. However, until c++14, there are additional restrictions on what is allowed for a pointer template argument.
C++14 draft N4140 [temp.arg.nontype]
1 A template-argument for a non-type, non-template template-parameter shall be one of:
for a non-type template-parameter of integral or enumeration type, a converted constant expression (5.19) of the type of the
template-parameter; or
the name of a non-type template-parameter; or
a constant expression (5.19) that designates the address of a complete object with static storage duration and external or internal
linkage or a function with external or internal linkage, including
function templates and function template-ids but excluding non-static
class members, expressed (ignoring parentheses) as
&id-expression, where the id-expression is the name of an object or
function, except that the & may be omitted if the name refers to a
function or array and shall be omitted if the corresponding
template-parameter is a reference; or
a constant expression that evaluates to a null pointer value (4.10); or
a constant expression that evaluates to a null member pointer value (4.11); or
a pointer to member expressed as described in 5.3.1; or
a constant expression of type std::nullptr_t.
For foo<dum_ptr>(), dum_ptr isn't expressed as &name, and for foo<&dum_ref>(), dum_ref isn't the name of the object, it's the name of a reference to the object, so both are disallowed as template arguments.
These restrictions are lifted in c++17 to allow any constexpr, so thats why it works there:
C++17 draft N4606 - 14.3.2 Template non-type arguments [temp.arg.nontype]
1 A template-argument for a non-type template-parameter shall be a
converted constant expression (5.20) of the type of the
template-parameter. For a non-type template-parameter of reference or
pointer type, the value of the constant expression shall not refer to
(or for a pointer type, shall not be the address of):
(1.1) a subobject (1.8),
(1.2) a temporary object (12.2),
(1.3) a string literal (2.13.5),
(1.4) the result of a typeid expression (5.2.8), or
(1.5) a predefined __func__ variable (8.4.1).
As usual, clang gives the best error messages:
https://godbolt.org/g/j0Q2bV
*(see Address constant expression and Reference constant expression)

Related

Why does delegating to the default constructor not zero initialize member variable

#include <string>
struct T1 {
int _mem1;
int _mem2;
T1() = default;
T1(int mem2) : T1() { _mem2 = mem2; }
};
T1 getT1() { return T1(); }
T1 getT1(int mem2) { return T1(mem2); }
int main() {
volatile T1 a = T1();
std::printf("a._mem1=%d a._mem2=%d\n", a._mem1, a._mem2);
volatile T1 b = T1(1);
std::printf("b._mem1=%d b._mem2=%d\n", b._mem1, b._mem2);
// Temporarily disable
if (false) {
volatile T1 c = getT1();
std::printf("c._mem1=%d c._mem2=%d\n", c._mem1, c._mem2);
volatile T1 d = getT1(1);
std::printf("d._mem1=%d d._mem2=%d\n", d._mem1, d._mem2);
}
}
When I compile this with gcc5.4, I get the following output:
g++ -std=c++11 -O3 test.cpp -o test && ./test
a._mem1=0 a._mem2=0
b._mem1=382685824 b._mem2=1
Why does the user defined constructor, which delegates to the default constructor not manage to set _mem1 to zero for b, however a which uses the default constructor is zero initialized?
Valgrind confirms this also:
==12579== Conditional jump or move depends on uninitialised value(s)
==12579== at 0x4E87CE2: vfprintf (vfprintf.c:1631)
==12579== by 0x4E8F898: printf (printf.c:33)
==12579== by 0x4005F3: main (in test)
If I change if(false) to if(true)
Then the output is as you would expect
a._mem1=0 a._mem2=0
b._mem1=0 b._mem2=1
c._mem1=0 c._mem2=0
d._mem1=0 d._mem2=1
What is the compiler doing?
Short answer: for trivial types, the two distinct forms of "default construction" leads to two different initializations:
T a; in which case the object is default-initialized. Its value is undetermined and undefined behavior will soon happen (this is how is initialized b.mem1 and why valgrind detect an error.)
T a=T(); in which case the object is value-initialized and its entire memory is zeroed (this is what happens to a.mem1 and a.mem2)
Long answer: Actualy, the default constructor of T1 is not the cause of zero initialization of a.mem1. a has been first zero-initialized but not b because of a singular rule of the standard that does not apply for b's initializer.
The definition volatile a=T() causes a to be value-initialized (1). struct T1 as no user-provided default constructor (2). For such a struct the entire object is zero-initialized as stated by this rule of the C++11 standard [dcl.init]/7.2:
if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T's implicitly-declared default constructor is non-trivial, that constructor is called.
There is a subtle difference between C++11 and C++17 that causes the definition volatile b=T(1) to be undefined behavior in C++11 but not in C++17. In C++11, b is initialized by copying an object type T1 which is initialized by the expression T(1). This copy construction evaluate T(1).mem1 which is an undetermined value. This is forbidden. In c++17, b is directly initialized by the prvalue expression T(1).
The evaluation of this undetermined value inside the printf is also undefined behavior independently of the c++ standard. This is why valgrind complains and why you see inconsistent outputs when you change if (true) to if (false).
(1) strictly speaking a is copy constructed from a value-initalized object in c++11
(2) T1's default constructor is not user provided because it is defined as defaulted on the first declaration
Short Answer
The default constructor in your code is considered trivial and that kind of constructor perform no actions i.e. leave things unitialized.
Longer answer
Trivial default constructor
The default constructor for class T is trivial (i.e. performs no
action) if all of the following is true:
The constructor is not user-provided (i.e., is implicitly-defined or defaulted on its first declaration)
T has no virtual member functions
T has no virtual base classes
T has no non-static members with default initializers.
(since C++11)
Every direct base of T has a trivial default constructor
Every non-static member of class type has a trivial default constructor
> A trivial default constructor is a constructor that performs no
action. All data types compatible with the C language (POD types) are
trivially default-constructible. Unlike in C, however, objects with
trivial default constructors cannot be created by simply
reinterpreting suitably aligned storage, such as memory allocated with
std::malloc: placement-new is required to formally introduce a new
object and avoid potential undefined behavior.
http://www.enseignement.polytechnique.fr/informatique/INF478/docs/Cpp/en/cpp/language/default_constructor.html

Code explanation of the json11 library about implicit constructor

I'm reading the source code of the main json11 header file.
It contains the following declaration:
template <class T, class = decltype(&T::to_json)>
Json(const T & t) : Json(t.to_json()) {}
I'm trying to find some documentation about this usage of decltype and class inside a template declaration but no success.
Does this construction/usage has a name in C++? Any good reference about it?
It's using SFINAE ("Substitution Failure Is Not An Error"), a common technique for advanced template stuff. In this case, it's used as a crude(1) test whether the type T has a function named to_json.
How it works: if the expression T::to_json is well-formed (there is something named to_json inside the type T), decltype(T::to_json) denotes a valid type and the constructor template can be used normally.
However, if T::to_json is ill-formed (i.e. if there is no to_json member inside T), it means substituting the template argument for T has failed. Per SFINAE, this is not an error of the entire program; it just means that the template is removed from further consideration (as if it was never part of the class).
The effect is thus that if type T has a member to_json, you can use an object of type T to initialise a Json object. If there is no such member in T, the constructor will not exist.
(1) I'm saying crude test because this only checks that T has such a member. It doesn't check that the member is a function which can be invoked without arguments and returns something another constructor of Json can accept. A tighter-fitting test might look something like this:
template <class T, class = std::enable_if_t<std::is_constructible<Json, decltype(std::declval<const T>().to_json())>::value>>
Json(const T & t) : Json(t.to_json()) {}
[Live example]

Defining a variable in Go programming language

I am learning Go language and comes across seeing this type of variable declaration:
i:=1;
But it says that Go has static variables. i,e variables should be defined in some way like this
var i int=1;
So what is the difference between these two methods? In the first one we don't need to indicate the data type. Why is it so?
The first one i := 1 is called short variable declaration. It is a shorthand for regular variable declaration with initializer expressions but no types:
var IdentifierList = ExpressionList
You don't specify the type of i, but i will have a type based on certain rules. Its type will be automatically inferred. In this case it will be of type int because the initializer expression 1 is an untyped integer constant whose default type is int, so when a type is needed (e.g. it is used in a short variable declaration), int type will be deduced.
So Go is statically typed. That means variables will have a static type and values stored in them at runtime will always be of that type. Being statically typed does not mean you have to explicitly specify the static type, it just means variables must have a static type - decided at compile time - which condition is met even if you use short variable declaration and you don't specify it.
Note that you can also omit the type if you declare a variable with the var keyword:
var i = 1
In which case the type will also be deduced from the type of the initializer expression.
Spec: Variable declaration:
If a type is present, each variable is given that type. Otherwise, each variable is given the type of the corresponding initialization value in the assignment. If that value is an untyped constant, it is first converted to its default type; if it is an untyped boolean value, it is first converted to type bool. The predeclared value nil cannot be used to initialize a variable with no explicit type.
Go is designed with ease of use in mind. So new variables are able to get an implicit type of the right side using the := operator. Also the constant 1 for example has an implicit type in go.

Lambda expression in c++, OS X's clang vs GCC

A particular property of c++'s lambda expressions is to capture the variables in the scope in which they are declared. For example I can use a declared and initialized variable c in a lambda function even if 'c' is not sent as an argument, but it's captured by '[ ]':
#include<iostream>
int main ()
{int c=5; [c](int d){std::cout<<c+d<<'\n';}(5);}
The expected output is thus 10. The problem arises when at least 2 variables, one captured and the other sent as an argument, have the same name:
#include<iostream>
int main ()
{int c=5; [c](int c){std::cout<<c<<'\n';}(3);}
I think that the 2011 standard for c++ says that the captured variable has the precedence on the arguments of the lambda expression in case of coincidence of names. In fact compiling the code using GCC 4.8.1 on Linux the output I get is the expected one, 5. If I compile the same code using apple's version of clang compiler (clang-503.0.40, the one which comes with Xcode 5.1.1 on Mac OS X 10.9.4) I get the other answer, 3.
I'm trying to figure why this happens; is it just an apple's compiler bug (if the standard for the language really says that the captured 'c' has the precedence) or something similar? Can this issue be fixed?
EDIT
My teacher sent an email to GCC help desk, and they answered that it's clearly a bug of GCC compiler and to report it to Bugzilla. So Clang's behavior is the correct one!
From my understanding of the c++11 standard's points below:
5.1.2 Lambda expressions
3 The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type — called
the closure type — whose properties are described below.
...
5 The closure type for a lambda-expression has a public inline function call operator (13.5.4) whose parameters and return type are
described by the lambda-expression’s parameter-declaration-clause and
trailing-return-type respectively. This function call operator is
declared const (9.3.1) if and only if the lambda-expression’s
parameter-declaration-clause is not followed by mutable.
...
14 For each entity captured by copy, an unnamed non static data member is declared in the closure type
A lambda expression like this...
int c = 5;
[c](int c){ std::cout << c << '\n'; }
...is roughly equivalent to a class/struct like this:
struct lambda
{
int c; // captured c
void operator()(int c) const
{
std::cout << c << '\n';
}
};
So I would expect the parameter to hide the captured member.
EDIT:
In point 14 from the standard (quoted above) it would seem the data member created from the captured variable is * unnamed *. The mechanism by which is it referenced appears to be independent of the normal identifier lookups:
17 Every id-expression that is an odr-use (3.2) of an entity captured by copy is transformed into an access to the corresponding unnamed data member of the closure type.
It is unclear from my reading of the standard if this transformation should take precedence over parameter symbol lookup.
So perhaps this should be marked as UB (undefined behaviour)?
From the C++11 Standard, 5.1.2 "Lambda expressions" [expr.prim.lambda] #7:
The lambda-expression’s compound-statement yields the function-body (8.4) of the function call operator,
but for purposes of name lookup (3.4), determining the type and value of this (9.3.2) and transforming id-expressions
referring to non-static class members into class member access expressions using (*this) (9.3.1),
the compound-statement is considered in the context of the lambda-expression.
Also, from 3.3.3 "Block scope" [basic.scope.local] #2:
The potential scope of a function parameter name (including one appearing in a lambda-declarator) or of
a function-local predefined variable in a function definition (8.4) begins at its point of declaration.
Names in a capture list are not declarations and therefore do not affect name lookup. The capture list just allows you to use the local variables; it does not introduce their names into the lambda's scope. Example:
int i, j;
int main()
{
int i = 0;
[](){ i; }; // Error: Odr-uses non-static local variable without capturing it
[](){ j; }; // OK
}
So, since the parameters to a lambda are in an inner block scope, and since name lookup is done in the context of the lambda expression (not, say, the generated class), the parameter names indeed hide the variable names in the enclosing function.

Is gcc doing implicit function declarations incorrectly in c99 mode?

Consider the following code:
int main (void) {
int i = xyzzy();
return i;
}
int xyzzy (void) {
return 42;
}
Now, although the prototype for xyyzy is unkown at the point of use, this works in c89 mode because the default return type of a function that has no prototype is int so the implicit function prototype and actual function are compatible.
And, in fact, if you change the return type of the function to float, you get (as expected):
testprog.c:6: error: conflicting types for 'xyzzy'
testprog.c:2: error: previous implicit declaration of 'xyzzy' was here
because the implicit prototype and actual function no longer match.
The original code compiled with gcc --std=c89 --pedantic -Wall -Wextra only gives me the warning:
testprog.c: In function 'main':
testprog.c:2: warning: implicit declaration of function 'xyzzy'
which is expected, because c89 has this to say in 3.7.1 Function definitions:
extern int max(int a, int b) { ... }: Here extern is the storage-class specifier and int is the type specifier (each of which may be omitted as those are the defaults).
and in 3.3.2.2 Function calls:
If the expression that precedes the parenthesized argument list in a function call consists solely of an identifier, and if no declaration is visible for this identifier, the identifier is implicitly declared exactly as if, in the innermost block containing
the function call, the declaration extern int identifier(); appeared.
So the use of a function before declaring it definitely results in the default prototype being created.
However, both those phrases have been removed in c99 and we instead find in 6.5.2.2 Function calls (my bold):
If the expression that denotes the called function has type pointer to function returning an object type, the function call expression has the same type as that object type, and has the value determined as specified in 6.8.6.4. Otherwise, the function call has type void.
I understand it to mean that, if there's no declaration in view when you try to call a function, it's implicitly declared with a void return type.
Yet, when compiling with gcc --std=c99 --pedantic -Wall -Wextra, I get just the same warning about the implicit declaration.
Shouldn't c99 have declared that function implicitly as returning void? If it had, I would have expected a previous implicit declaration error similar to the one I got when I tried to redeclare it as returning float.
Is gcc broken here, or am I missing something in the standard?
You are reading the standard incorrectly. There's no such thing as implicit function declaration in C. It is removed from the language by C99.
GCC issues a warning when it sees an erroneous construct that looks like an implicit function declaration. This is OK as far as the standard is concerned. The standard requires a diagnostic here, and a warning is a diagnostic. You may use -Werror=implicit-function-declaration flag to GCC to turn this into an error.
This is covered in a note to 6.5.1 Primary expressions:
2 - An identifier is a primary expression, provided it has been declared as designating an
object (in which case it is an lvalue) or a function (in which case it is a function
designator). 79)
79) Thus, an undeclared identifier is a violation of the syntax.
A conforming implementation is required by 5.1.1.3 Diagnostics to produce a diagnostic message in response to the syntax violation of a function call expression involving an undeclared identifier as the expression denoting the called function. It is of course free to proceed to compile the program as if the identifier had been declared in the implicit-int C89 style.
The paragraph 6.5.2.2p5 must be read with reference to the constraint 6.5.2.2p1:
1 - The expression that denotes the called function shall have type pointer to function
returning void or returning an object type other than an array type.
So, if the "expression that denotes the called function" does not have type "pointer to function returning an object type", it must ipso facto (by the constraint 6.5.2.2p1) have type "pointer to function returning void", and it is this case which the "Otherwise" in 6.5.2.2p5 covers. That is, with my insertion in [square brackets]:
5 - If the expression that denotes the called function has type pointer to function returning an object type, the function call expression has the same type as that object type, and has the value determined as specified in 6.8.6.4. Otherwise, [i.e. if the expression that denotes the called function has type pointer to function returning void,] the function call has type void.
This is a case of special language being required for void as opposed to object types; is not a licence for the called function expression to be or contain an undeclared identifier.

Resources