2016-01-25 4 views
2

У меня есть шаблон класса Foo с помощью следующей функции члена:Передача const это функции, принимающей указатель const не const-correct?

bool contains(const T& item) const 

Я инстанцированный это с типом указателя: Foo<Bar*>, что привело меня ожидать, что функция член теперь будет иметь следующий вид:

bool contains(const Bar*& item) const 

в функции в constBar член, я пытаюсь передать this в Foo<Bar*>::contains:

bool Bar::func(const Foo<Bar*>& foo) const 
{ 
    return foo.contains(this); 
} 

Это не может скомпилировать, со следующей ошибкой:

error: invalid conversion from ‘ const Bar* ’ to ‘ Bar*

Вопрос:

  • Почему мой параметр const T& не сопзЬ-правильно?
  • Какая подпись для Foo<T>::contains(...) const требуется для звонка с this для компиляции?

Полный пример: выход

#include <vector> 
#include <algorithm> 

template<typename T> 
struct Foo 
{ 
    bool contains(const T& item) const 
    { 
     return false; 
    } 
}; 

struct Bar 
{ 
    bool func(const Foo<Bar*>& foo) const 
    { 
     return foo.contains(this); 
    } 
}; 

Ошибка:

scratch/main.cpp:17:33: error: invalid conversion from ‘const Bar*’ to ‘Bar*’ [-fpermissive] 
     return foo.contains(this); 
           ^
scratch/main.cpp:7:10: note: initializing argument 1 of ‘bool Foo<T>::contains(const T&) const [with T = Bar*]’ 
    bool contains(const T& item) const 

ответ

5

I have instantiated this with a pointer type: Foo<Bar*> , leading me to expect that the member function will now have the following signature:

bool contains(const Bar*& item) const 

Вот где проблема. Когда T = Bar* выражение

bool contains(const T& item) const 

будет скомпилирован в

bool contains(Bar * const & item) const 

То есть, ссылка к-а-сопзЬ-указатель на бар. У вас есть смысл думать об этом: вы хотите, чтобы T был const, а затем вам нужна ссылка на это.

Если вы хотите применить сопзЬ в обычном «предназначен» пути (хотя это может вызвать некоторые сюрпризы для выдержанных C++ программистов), вы можете объявить контейнер и функцию-член следующим образом:

template <class T> 
class Container { 
public: 
    using const_bare_type = typename std::conditional< 
     std::is_pointer<T>::value, 
     typename std::remove_pointer<T>::type const*, 
     const T>::type; 

    bool contains(const const_bare_type& item); 
}; 
+0

Могу ли я внести какие-либо изменения в функцию члена 'Foo' в порядке чтобы позволить мне передать «это»? –

+0

@SteveLorimer Нет, ошибка возникает при создании экземпляра 'Foo ', см. Мой ответ. – vladon

+0

@SteveLorimer Это неудобно, но да. См. Мое редактирование. –

0

компилятора предупреждения о неправильной линии, вы должны написать:

bool func(const Foo<const Bar*>& foo) const 

. I. const Bar* в параметре шаблона, поскольку Bar::func принимает в качестве параметра const Bar * this и не может преобразовать его в Bar* в параметр шаблона (не удается удалить const).

+0

Я не верю, что могу изменить 'Foo ' на 'Foo ' могу ли я? –

+0

@SteveLorimer Конечно, вы можете. – vladon

+0

[Компилятор видит foo и foo как два совершенно разных и несвязанных типа] (http://stackoverflow.com/a/2290590/955273) –

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