3

I have a problem with a compiler error, take a look at this code:

template<class T>
struct MyStruct
{
};

template<>
struct MyStruct<int>
{
    typedef int* type;
};

template<class T>
void foo(const typename MyStruct<T>::type myType)
{
}

int main()
{
    const int* ptr = NULL;
    foo<int>(ptr);

    return 0;
}

The problem is that the compiler is ignoring the 'const' on foo function, making the call to foo illegal (const int* to int*).

Severity Code Description Project File Line Suppression State Error C2664 'void foo(const MyStruct::type)': cannot convert argument 1 from 'const int *' to 'const MyStruct::type'

I have tested the following code in Visual studio's and gcc's 5.3 complier, both of them dropping the same error.

Does the complier doing this on purpose? why is this happening?

Paul Floyd
  • 5,530
  • 5
  • 29
  • 43
UdiM
  • 480
  • 3
  • 19

1 Answers1

8

There is an important distinction between const int * and int * const. See this answer for an explanation of the difference.

Consider what const typename MyStruct<T>::type means. It's a MyStruct<T>::type that is const. In this case, it's an int* that is const. This is a int* const, a pointer which can't be reassigned a new address but that can still be used to modify the pointed int. However, the pointer you are passing in foo<int>(ptr) is a const int * which cannot be converted to int * const, as it would be discarding the const qualifier.

To achieve what you want, const must be part of the type before making it a pointer. It can't be added after the fact or it will always be interpreted as T * const. You can use type traits to remove the pointer part of the type, add const and then make it a pointer.

#include <type_traits>

template<class T>
struct MyStruct { };

template<>
struct MyStruct<int> {
    typedef int* type;
};

template<class T>
void foo( std::add_const_t<std::remove_pointer_t<typename MyStruct<T>::type>> * myType) {}

int main()
{
    const int* ptr = nullptr;
    foo<int>(ptr);

    return 0;
}
Community
  • 1
  • 1
François Andrieux
  • 28,148
  • 6
  • 56
  • 87