I'm attempting to solve a problem in which decltype
will greatly simplify things, but I'm running into an issue using decltype
on *this
and adding a const
qualifier. The sample code below demonstrates the problem.
#include <iostream>
struct Foo
{
void bar()
{
static_cast<const decltype(*this)&>(*this).bar();
}
void bar() const
{
std::cout << "bar" << std::endl;
}
};
int main(int argc, char* argv[])
{
Foo f;
f.bar(); // calls non-const method
return 0;
}
The code compiles in MSVC2010, but execution recurses until a stack overflow occurs.
Ideone reports compiler error
prog.cpp: In member function 'void Foo::bar()':
prog.cpp:7:38: error: 'const' qualifiers cannot be applied to 'Foo&'
If I change the line
static_cast<const decltype(*this)&>(*this).bar();
to
static_cast<const Foo&>(*this).bar();
it works as expected.
Am I misusing or misunderstanding decltype?
const_cast is one of the type casting operators. It is used to change the constant value of any object or we can say it is used to remove the constant nature of any object. const_cast can be used in programs that have any object with some constant value which need to be changed occasionally at some point.
The decltype type specifier yields the type of a specified expression. The decltype type specifier, together with the auto keyword, is useful primarily to developers who write template libraries. Use auto and decltype to declare a function template whose return type depends on the types of its template arguments.
Since the expression *this
is not an id-expression (i.e. it doesn't name an entity, like a variable), then decltype(*this)
gives the type of the expression *this
. That type is Foo&
, so adding a const
qualifier and making a reference to that doesn't change anything: either it silently collapse to Foo&
(following rules like reference collapsing), or it's an error (a const reference type). I'm not sure which behaviour is correct, and you have in fact found two compilers which behave differently. In any case it doesn't matter because it's not what you want.
You can use std::remove_reference<decltype(*this)>::type const&
instead but that looks a bit ugly.
In case you're still confused:
int* p;
// decltype(p) is the type of the variable p (or, the declared type)
// int*
// decltype( (p) ) is the type of the expression p
// int*& because p is an lvalue
// decltype(*p) is the type of the expression *p
// int& because *p is an lvalue
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With