Why exactly is this template function successfully compiling? [duplicate] - c++

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
Destructors of builtin types (int, char etc..)
Template Function:
template<typename T> void kill(T* type)
{
type->~T();
}
Call:
int x= 5;
kill(&x);
woah, it compiled!? How can a primitive type like int have a destructor? It is also working with char , bool etc.

§12.4.16 of the Standard says
16 [ Note: the notation for explicit call of a destructor can be used for any scalar type
name (5.2.4). Allowing this makes it possible to write code without having to know if a
destructor exists for a given type. For example,
typedef int I;
I* p;
p->I::~I();
—end note ]

The relevant part of the standard is §5.2.4/1:
The use of a pseudo-destructor-name after a dot . or arrow -> operator represents the destructor for the non-class type named by type-name. The result shall only be used as the operand for the function call operator (), and the result of such a call has type void. The only effect is the evaluation of the postfix expression before the dot or arrow.

Related

can not make sens of this type `void(C::* volatile)(int) const ` used in an example in C++ reference manual [duplicate]

This question already has answers here:
Can somebody explain this C++ typedef?
(4 answers)
Pointer to class data member "::*"
(18 answers)
Closed 3 years ago.
In the C++17 standard draft document, in subsection (6.7.3) "CV-qualifiers" [basic.type.qualifier]:
paragraph 6, there is this sentence:
For a class type C, the type corresponding to the type-id void(C::* volatile)(int) const
has the top-level cv-qualifier volatile.
I have C language background and was randomly reading C++ standard and can't make sens of this, I tried to interpret it as
a volatile function pointer to a function that can be called on const objects and that takes a single int argument and return a ??? ( C type / void I am lost here)
does someone have an explanation ?
I have tried this code
int main()
{
class C
{
public:
typedef void(C:: * volatile X)(int)const ;
void f(int z) const
{cout << z << endl;}
X a = (X)&f; // had to add -fpermissive flag
};
C t;
t.f(5); // works obviously
(t.a)(5); // gives the following compilation message
main.cpp:22:18: warning: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say ‘&main()::C::f’ [-fpermissive]
X a = (X)&f;
^
main.cpp:27:12: error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘t.main()::C::a (...)’, e.g. ‘(... ->* t.main()::C::a) (...)’
(t.a)(5);
^
changing to what is adviced doesn't work !
thank you for your help
The C::* syntax denotes a member-function pointer which means a pointer to a member-function (sometimes called a method) that belongs to a class C.
In order to obtain an address of a member-function you need to use special syntax with qualified member-function name:
X a = &C::f;
In order to call a member-function via pointer you need to use a special operator .* (as your compiler advises):
(t.*(t.a))(5);
Note that we need to use t twice: for accessing a member and for calling a with t as this.

Can a C++ default argument be initialized with another argument? [duplicate]

This question already has answers here:
Can I set a default argument from a previous argument?
(7 answers)
Closed 5 years ago.
For a default argument in C++, does the value need to be a constant or will another argument do?
That is, can the following work?
RateLimiter(unsigned double rateInPermitsPerSecond,
unsigned int maxAccumulatedPermits = rateInPermitsPerSecond);
Currently I am getting an error:
RateLimiter.h:13: error: ‘rateInPermitsPerSecond’ was not declared in this scope
Another argument cannot be used as the default value. The standard states:
8.3.6 Default arguments...
9 A default argument is evaluated each time the function is called with no argument for the corresponding
parameter. The order of evaluation of function arguments is unspecified. Consequently, parameters of a
function shall not be used in a default argument, even if they are not evaluated.
and illustrates it with the following sample:
int f(int a, int b = a); // error: parameter a
// used as default argument
No, that cannot work because the evaluation of function arguments is not sequenced. It also does not work because the standard does not allow it, but I guess that was obvious.
Use an overload instead:
void fun(int, int) {}
void fun(int i) {
fun(i, i);
}
I was looking for an logical explanation for why it is not allowed
This is actually a good question. The reason is that C++ does not mandate the order of evaluation of arguments.
So let's imagine a slightly more complex scenario:
int f(int a, int b = ++a);
... followed by ...
int a = 1;
f(a);
C++ does not mandate the order of evaluation of arguments, remember?
So what should be the value of b?
f(a) can evaluate to either:
f(1, 2), or
f(2, 2), depending on the order of evaluation of the arguments.
Thus the behaviour would be undefined (and even undefinable).
Further, consider what might happen when a and b were complex objects whose constructors and copy operators had side-effects.
The order of those side-effects would be undefined.
You cannot do things like that because the standard does not allow it. However since default arguments effectively just define new function overloads, you can get the desired effect by explicitly defining such an overload:
void RateLimiter(unsigned int rateInPermitsPerSecond,
unsigned int maxAccumulatedPermits);
inline void RateLimiter(unsigned int rateInPermitsPerSecond)
{ return RateLimiter(rateInPermitsPerSecond,rateInPermitsPerSecond); }
This shows that the standard forbidding this is half-hearted, as suggested by the language ("Consequently... shall not..."). They just did not want to go through the hassle of making this well defined with the same effect as what the explicit overload declaration would do: if desired, they could have specified that defaulted arguments are evaluated after explicitly provided ones, and from left to right. This would not have any influence on the rule that the evaluation order of argument expressions in a function call is unspecified (because default arguments do not correspond to such expressions; they are entirely separate and not even in the same lexical scope). On the other hand if (as they did) they preferred to disallow this, they could have just said "shall not" without need to justify themselves from some other rule (but maybe with explanatory footnote).
For a default argument in C++, does the value need to be a constant or will another argument do?
The default value of an argument cannot be another argument. However, that does not mean it has to be a constant. It can be the return value of a function call.
int getNextDefaultID()
{
static int id = 0;
return ++id;
}
struct Foo
{
Foo(int data, int id = getNextDefaultID()) : data_(data), id_(id) {}
int data_;
int id_;
};
int main()
{
Foo f1(10); // Gets the next default ID.
Foo f2(20, 999); // ID is specified.
}

Overloading type cast operator, to cast to a pointer to function [duplicate]

This question already has answers here:
C++ Conversion operator for converting to function pointer
(6 answers)
Closed 8 years ago.
I'm having some difficulty, overloading the cast to pointer to function operator of a class. In code, what I want is this:
typedef int(*funcptrtype)(int);
struct castable {
operator funcptrtype() {return NULL;}
};
but I want to be able to do it without using the typedef. If you're curious, I need this, because pre-c++11 template aliases aren't available (so the typedef trick is not an option in templated contexts...)
I would normally expect this to work:
operator int(*)(int)() {return NULL;}
But it doesn't. The compiler (g++ 4.6.1) says:
error: ‘<invalid operator>’ declared as function returning a function
This works:
int (* operator()())(int){return 0;}
But you're actually overloading the operator() to return a function pointer :)
The standard says:
The conversion-type-id shall not represent a function type nor an
array type
But it doesn't say function pointer type (The first code snipplet works anyway...).
Does anyone know the right syntax w/o typedef?
The grammar doesn't allow this: the type in a conversion operator declaration is a type-specifier, not a type-id. You have to use a typedef or alias; in a template context, use the usual replacement:
template<typename T>
struct something {
typedef T (*type)(int);
};

What does the C++ standard say about the difference between casting from type a to type b, and instantiating/Constructing type b? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What is the difference between (type)value and type(value)?
If you have a function that takes an argument of type b, but at the call site you only have a variable of type a. Is there a difference between casting the function parameter from a to b, and constructing type b.
The specific example I am interested in is when there is no user defined cast operator, but there is a single argument constructor.
Example:
Function definition:
void DoWork(const B &arg1);
In my specific example type a is const char *
Call site:
DoWork((B)"Hello");
vs
DoWork(B("Hello"));
B class definition
class B
{
public:
B() : m_szValue(){}
B(const char *szValue) { strcpy (m_szValue, szValue); }
private:
char m_szValue[MAX_VALUE_LEN + 1];
};
Writing a C-style cast (T)x, where x is of type U, more or less tries the following in order:
If T and U are of class type, look for a conversion operator U::operator T() const or a one-argument constructor T::T(U).
If T and U are primitive types, apply the standard value conversions (int to double, etc.).
reinterpret_cast<T>(x).
Note that you mustn't have both a conversion operator and implicit conversion construction, though, or the call will be ambiguous.
[Correction/Clarification:] There is no difference between T(x) and (T)x.[/] You can even say DoWork("Hello"); on account of the implicit conversion provided by the one-argument constructor. (Do disallow this sneaky behaviour, declare the constructor explicit, as is often a good idea for one-argument constructors.)

Reference to member function? [duplicate]

This question already has an answer here:
Why doesn't reference-to-member exist in C++?
(1 answer)
Closed 9 years ago.
I recently find out that there is a reference-to-function concept in C++ :).
So as there are pointer-to-function and pointer-to-member-function different types. The question arises. Is there a "reference-to-member-function" concept?
I tried to compile the following code, but GCC 3.4.6 gives an error.
#include <iostream>
using namespace std;
class A {
public:
virtual void Af() const {
cout << "A::Af()" << endl;
}
};
int main() {
typedef void (A::& MemFnc)() const;
MemFnc mf = &A::Af;
A a;
(a.*mf)();
return 0;
}
There is no such a thing called reference to member in C++.
The language specification explicitly says in a note (§8.3.3/3 - 2003) that,
A pointer to member shall not point to a static member of a class (9.4), a member with reference type, or “cv void.” [Note: see also 5.3 and 5.5. The type “pointer to member” is distinct from the type “pointer”, that is, a pointer to member is declared only by the pointer to member declarator syntax, and never by the pointer declarator syntax. There is no “reference-to-member” type in C++.
No, references to member functions are not possible.
In some sense, the result of dereferencing a pointer to a member function could serve as one, but the only thing you can do with that result is to invoke a function call operator on it, per 5.5[expr.mptr.oper]/6. Nothing else is allowed.
There is no reference to member function.