The following code is excerpted from cppreference.com.
#include
#include
struct foo
{
void m() { std::cout <<
This appears to be a bug with MSVC. Using an expression of the form T()
(which is an explicit type conversion, as far as the standard is concerned) results in a prvalue of the specified type.
The expression
T()
, whereT
is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv-qualified)void
type, creates a prvalue of the specified type, which is value-initialized
It is only with non-class types that the const
would be ignored, due to a rule that non-class prvalues cannot have cv-qualified types:
Class prvalues can have cv-qualified types; non-class prvalues always have cv-unqualified types.
So the temporary object created by T()
here should be const
and should therefore call the const
member function.
As for when and why you would use std::add_const
, we can take a look at the reason it was included in the proposal. It states that the add_const
, add_volatile
, add_cv
, add_pointer
, and add_reference
type traits were removed from the proposal but then reinstated after complaints from users of Boost.
The rationale is that these templates are all used as compile time functors which transform one type to another [...]
The example given is:
// transforms 'tuple<T1,T2,..,Tn>'
// to 'tuple<T1 const&,T2 const&,..,Tn const&>'
template< typename Tuple >
struct tuple_of_refs
{
// transform tuple element types
typedef typename mpl::transform<
typename Tuple::elements,
add_reference< add_const<_1> > // here!
>::type refs;
typedef typename tuple_from_sequence<refs>::type type;
};
template< typename Tuple >
typename tuple_of_refs<Tuple>::type
tuple_ref(Tuple const& t)
{
return typename tuple_of_refs<Tuple>::type(t);
}
You can think of mpl::transform
as taking the compile-time metaprogramming equivalent to a function pointer as its second template argument - add_reference<add_const<...>>
is applied to each of the types in Tuple::elements
. This simply couldn't be expressed using const
.
From what i remember it goes as follows, you can write 3 consts(3 is the number of purpose) in a function declaration.
before the return type, after the function and its parameters, and on the parameters themselves.
const at the end of a function signature means that the function should assume the object of which it is a member is const. In practical terms it means that you ask the compiler to check that the member function does not change the object data in any way. It means asking the compiler to check that it doesn't directly change any member data, and it doesn't call any function that itself does not guarantee that it won't change the object.
before the return type means the thing the function is to return should be a const.
const parameter means that the parameter cannot be changed.
so the difference here is, the first call is not a const so it goes to the "non-cv", the second call is a const and so goes to "const".
what i think of why VC++ goes to the same function both times is that call_m explicitly calls for T().m() thinking it shouldnt go to the const one.