2017-02-15 13 views
3

У меня есть проблема с ошибкой компилятора, посмотрите на этот код:Компилятор игнорирует «сопзЬ» на параметр функции

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; 
} 

Проблема заключается в том, что компилятор игнорирует «Const» на функции Foo, делая вызов foo незаконным (const int * to int *).

Тяжесть Код Описание проекта State Line File Подавление Error 'недействительным Foo (сопзЬ MyStruct :: тип)' C2664: не удается преобразовать аргумент 1 из 'Const ИНТ *' до 'сопзЬ MyStruct :: типа'

Я протестировал следующий код в Visual Studio и gcc 5.3 complier, оба из которых сбросили ту же ошибку.

Выполняет ли это соблюдение специально? почему это происходит?

+3

'const int * ptr' не является указателем константы, это указатель на const. – juanchopanza

ответ

7

Существует важное различие между const int * и int * const. См. this answer для объяснения разницы.

Рассмотрите, что такое const typename MyStruct<T>::type. Это MyStruct<T>::type, то есть const. В этом случае это int*, то есть const. Это int* const, указатель, который не может переназначить новый адрес, но который все еще может использоваться для изменения заостренного int. Однако указатель, который вы передаете в foo<int>(ptr), является const int *, который не может быть преобразован в int * const, так как он будет отбрасывать квалификатор const.

Чтобы достичь желаемого, const должен быть частью этого типа, прежде чем сделать его указателем. Он не может быть добавлен после факта или всегда будет интерпретироваться как T * const. Вы можете использовать свойства типа, чтобы удалить указательную часть типа, добавить константу и затем сделать ее указателем.

#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; 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^