A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://timsong-cpp.github.io/cppwp/n4140/dcl.type below:

[dcl.type]

7.1.6.1 The cv-qualifiers [dcl.type.cv]

Note: Declaring a variable const can affect its linkage ([dcl.stc]) and its usability in constant expressions ([expr.const]). As described in [dcl.init], the definition of an object or subobject of const-qualified type must specify an initializer or be subject to default-initialization.  — end note ]

A pointer or reference to a cv-qualified type need not actually point or refer to a cv-qualified object, but it is treated as if it does; a const-qualified access path cannot be used to modify an object even if the object referenced is a non-const object and can be modified through some other access path. [ Note: Cv-qualifiers are supported by the type system so that they cannot be subverted without casting ([expr.const.cast]).  — end note ]

Except that any class member declared mutable ([dcl.stc]) can be modified, any attempt to modify a const object during its lifetime ([basic.life]) results in undefined behavior. [ Example:

const int ci = 3;               ci = 4;                         
int i = 2;                      const int* cip;                 cip = &i;                       *cip = 4;                       
int* ip;
ip = const_cast<int*>(cip);     *ip = 4;                        
const int* ciq = new const int (3);     int* iq = const_cast<int*>(ciq);        *iq = 4;                                

For another example

struct X {
  mutable int i;
  int j;
};
struct Y {
  X x;
  Y();
};

const Y y;
y.x.i++;                        y.x.j++;                        Y* p = const_cast<Y*>(&y);      p->x.i = 99;                    p->x.j = 99;                    

 — end example ]

What constitutes an access to an object that has volatile-qualified type is implementation-defined. If an attempt is made to refer to an object defined with a volatile-qualified type through the use of a glvalue with a non-volatile-qualified type, the program behavior is undefined.

Note: volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation. Furthermore, for some implementations, volatile might indicate that special hardware instructions are required to access the object. See [intro.execution] for detailed semantics. In general, the semantics of volatile are intended to be the same in C++ as they are in C.  — end note ]

7.1.6.2 Simple type specifiers [dcl.type.simple]

The auto specifier is a placeholder for a type to be deduced ([dcl.spec.auto]). The other simple-type-specifiers specify either a previously-declared type, a type determined from an expression, or one of the fundamental types ([basic.fundamental]). Table [tab:simple.type.specifiers] summarizes the valid combinations of simple-type-specifiers and the types they specify.

Table

10

simple-type-specifiers

and the types they specify


Specifier(s) Type type-name the type named simple-template-id the type as defined in [temp.names] char “char” unsigned char “unsigned char” signed char “signed char” char16_t “char16_t” char32_t “char32_t” bool “bool” unsigned “unsigned int” unsigned int “unsigned int” signed “int” signed int “int” int “int” unsigned short int “unsigned short int” unsigned short “unsigned short int” unsigned long int “unsigned long int” unsigned long “unsigned long int” unsigned long long int “unsigned long long int” unsigned long long “unsigned long long int” signed long int “long int” signed long “long int” signed long long int “long long int” signed long long “long long int” long long int “long long int” long long “long long int” long int “long int” long “long int” signed short int “short int” signed short “short int” short int “short int” short “short int” wchar_t “wchar_t” float “float” double “double” long double “long double” void “void” auto placeholder for a type to be deduced decltype(expression) the type as defined below

When multiple simple-type-specifiers are allowed, they can be freely intermixed with other decl-specifiers in any order. [ Note: It is implementation-defined whether objects of char type are represented as signed or unsigned quantities. The signed specifier forces char objects to be signed; it is redundant in other contexts.  — end note ]

For an expression e, the type denoted by decltype(e) is defined as follows:

The operand of the decltype specifier is an unevaluated operand (Clause [expr]).

Example:

const int&& foo();
int i;
struct A { double x; };
const A* a = new A();
decltype(foo()) x1 = 0;         decltype(i) x2;                 decltype(a->x) x3;              decltype((a->x)) x4 = x3;       

 — end example ] [ Note: The rules for determining types involving decltype(auto) are specified in [dcl.spec.auto].  — end note ]

Note: in the case where the operand of a decltype-specifier is a function call and the return type of the function is a class type, a special rule ([expr.call]) ensures that the return type is not required to be complete (as it would be if the call appeared in a sub-expression or outside of a decltype-specifier). In this context, the common purpose of writing the expression is merely to refer to its type. In that sense, a decltype-specifier is analogous to a use of a typedef-name, so the usual reasons for requiring a complete type do not apply. In particular, it is not necessary to allocate storage for a temporary object or to enforce the semantic constraints associated with invoking the type's destructor. [ Example:

template<class T> struct A { ~A() = delete; };
template<class T> auto h()
  -> A<T>;
template<class T> auto i(T)       -> T;
template<class T> auto f(T)       -> decltype(i(h<T>()));                                                                                                       template<class T> auto f(T)       -> void;
auto g() -> void {
  f(42);                                                                                        }
template<class T> auto q(T)
  -> decltype((h<T>()));                                        void r() {
  q(42);                                                                                                                        }

 — end example ] — end note ]

7.1.6.4 auto specifier [dcl.spec.auto]

The auto and decltype(auto) type-specifiers designate a placeholder type that will be replaced later, either by deduction from an initializer or by explicit specification with a trailing-return-type. The auto type-specifier is also used to signify that a lambda is a generic lambda.

A program that uses auto or decltype(auto) in a context not explicitly allowed in this section is ill-formed.

When a variable declared using a placeholder type is initialized, or a return statement occurs in a function declared with a return type that contains a placeholder type, the deduced return type or variable type is determined from the type of its initializer. In the case of a return with no operand, the initializer is considered to be void(). Let T be the declared type of the variable or return type of the function. If the placeholder is the auto type-specifier, the deduced type is determined using the rules for template argument deduction. If the deduction is for a return statement and the initializer is a braced-init-list ([dcl.init.list]), the program is ill-formed. Otherwise, obtain P from T by replacing the occurrences of auto with either a new invented type template parameter U or, if the initializer is a braced-init-list, with std::initializer_list<U>. Deduce a value for U using the rules of template argument deduction from a function call ([temp.deduct.call]), where P is a function template parameter type and the initializer is the corresponding argument. If the deduction fails, the declaration is ill-formed. Otherwise, the type deduced for the variable or return type is obtained by substituting the deduced U into P. [ Example:

auto x1 = { 1, 2 };         auto x2 = { 1, 2.0 };       

 — end example ]

Example:

const auto &i = expr;

The type of i is the deduced type of the parameter u in the call f(expr) of the following invented function template:

template <class U> void f(const U& u);

 — end example ]

If the placeholder is the decltype(auto) type-specifier, the declared type of the variable or return type of the function shall be the placeholder alone. The type deduced for the variable or return type is determined as described in [dcl.type.simple], as though the initializer had been the operand of the decltype. [ Example:

int i;
int&& f();
auto           x3a = i;        decltype(auto) x3d = i;        auto           x4a = (i);      decltype(auto) x4d = (i);      auto           x5a = f();      decltype(auto) x5d = f();      auto           x6a = { 1, 2 }; decltype(auto) x6d = { 1, 2 }; auto          *x7a = &i;       decltype(auto)*x7d = &i;       

 — end example ]

If the init-declarator-list contains more than one init-declarator, they shall all form declarations of variables. The type of each declared variable is determined as described above, and if the type that replaces the placeholder type is not the same in each deduction, the program is ill-formed.

Example:

auto x = 5, *y = &x;        auto a = 5, b = { 1, 2 };   

 — end example ]

If a function with a declared return type that contains a placeholder type has multiple return statements, the return type is deduced for each return statement. If the type deduced is not the same in each deduction, the program is ill-formed.

If a function with a declared return type that uses a placeholder type has no return statements, the return type is deduced as though from a return statement with no operand at the closing brace of the function body. [ Example:

auto  f() { } auto* g() { } 

 — end example ]

If the type of an entity with an undeduced placeholder type is needed to determine the type of an expression, the program is ill-formed. Once a return statement has been seen in a function, however, the return type deduced from that statement can be used in the rest of the function, including in other return statements. [ Example:

auto n = n;            auto f();
void g() { &f; }       auto sum(int i) {
  if (i == 1)
    return i;            else
    return sum(i-1)+i; }

 — end example ]

Return type deduction for a function template with a placeholder in its declared type occurs when the definition is instantiated even if the function body contains a return statement with a non-type-dependent operand. [ Note: Therefore, any use of a specialization of the function template will cause an implicit instantiation. Any errors that arise from this instantiation are not in the immediate context of the function type and can result in the program being ill-formed.  — end note ] [ Example:

template <class T> auto f(T t) { return t; }  typedef decltype(f(1)) fint_t;                template<class T> auto f(T* t) { return *t; }
void g() { int (*p)(int*) = &f; }                                                           

 — end example ]

Redeclarations or specializations of a function or function template with a declared return type that uses a placeholder type shall also use that placeholder, not a deduced type. [ Example:

auto f();
auto f() { return 42; } auto f();               int f();                decltype(auto) f();     
template <typename T> auto g(T t) { return t; } template auto g(int);                           template char g(char);                          template<> auto g(double);                      
template <class T> T g(T t) { return t; } template char g(char);                    template auto g(float);                   
void h() { return g(42); } 
template <typename T> struct A {
  friend T frf(T);
};
auto frf(int i) { return i; } 

 — end example ]

A function declared with a return type that uses a placeholder type shall not be virtual ([class.virtual]).

An explicit instantiation declaration ([temp.explicit]) does not cause the instantiation of an entity declared using a placeholder type, but it also does not prevent that entity from being instantiated as needed to determine its type. [ Example:

template <typename T> auto f(T t) { return t; }
extern template auto f(int); int (*p)(int) = f;                                        

 — end example ]


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4