Why doesn't decltype(*this)
compile? It shows an error message:
error: 'value_type' is not a member of 'const Foo<char>&'
So what exactly is the reason that decltype( *this )::value_type
does not compile in the below program:
#include <iostream>
#include <vector>
#include <type_traits>
template <typename charT>
struct Foo
{
using value_type = charT;
std::vector<value_type> vec;
void print( ) const;
};
template <typename charT>
void Foo<charT>::print( ) const
{
using Foo_t = std::remove_reference_t<decltype( *this )>;
// `decltype( *this )::value_type` does not compile
if constexpr ( std::is_same_v< typename Foo_t::value_type,
decltype( std::cout )::char_type > )
{
// logic
}
else if constexpr ( std::is_same_v< typename Foo_t::value_type,
decltype( std::wcout )::char_type > )
{
// logic
}
else
{
static_assert( std::is_same_v< typename Foo_t::value_type,
decltype( std::cout )::char_type > ||
std::is_same_v< typename Foo_t::value_type,
decltype( std::wcout )::char_type >,
"character type not supported" );
}
}
int main( )
{
#define IS_CHAR 1
#if IS_CHAR == 1
using FooChar = Foo<char>;
FooChar foo;
foo.vec.resize( 10, '$' );
#else
using FooWideChar = Foo<wchar_t>;
FooWideChar foo;
foo.vec.resize( 10, L'#' );
#endif
foo.print( );
}
What is special about the this
pointer? Why does removing the reference with std::remove_reference_t
make it compile? Everything works in the above snippet. But if I replace typename Foo_t::value_type
with the more readable decltype( *this )::value_type
it won't compile. So I tried my luck by using std::remove_reference_t
and managed to come up with the above less straightforward (and less intuitive) solution:
using Foo_t = std::remove_reference_t<decltype( *this )>;
// and then inside the std::is_same_v
std::is_same_v< typename Foo_t::value_type, /* etc */ >
// ...
I know that there are more concise alternatives e.g. std::is_same_v< Foo<charT>::value_type,
or even std::is_same_v< charT,
but I find the decltype
approach more self-explanatory. Are there any other solutions?
The result of applying unary operator*
to a pointer is a reference (lvalue ref) to the pointed at value, not a copy of the pointed at value. So decltype(*this)
(or decltype(*foo)
for any pointer type) will always be a reference type. There's nothing special about this
.