C ++: объединить const с аргументами шаблона - PullRequest
3 голосов
/ 13 мая 2010

Следующий пример работает, когда я вручную заменяю T wirh char *, но почему не работает как есть:

template <typename T>
class A{
  public:
    A(const T _t) { }
};

int main(){
  const char * c = "asdf";
  A<char *> a(c);
}

При компиляции с gcc я получаю эту ошибку:

test.cpp: In function 'int main()':
test.cpp:10: error: invalid conversion from 'const char*' to 'char*'
test.cpp:10: error:   initializing argument 1 of 'A<T>::A(T) [with T = char*]'

Ответы [ 6 ]

10 голосов
/ 13 мая 2010

Подстановка T с char* дает указатель const на символ, а c объявляется как указатель на const char.

Решением было бы использование указателей и целочисленных типов по значению и типам классов по константной ссылке. Если вы можете, используйте Boost Call Traits , который решает такие проблемы для вас.

2 голосов
/ 13 мая 2010

Здесь происходит то, что компилятор знает, что ваш шаблон создан с помощью T = char*, и в первую очередь пытается определить, является ли значение, которое вы предоставляете (c), равным char* (это не так, это const char*) перед проверкой его постоянства.

Поэтому вам нужно либо:

  1. const_cast значение c
  2. Укажите A<const char *> a(c);
  3. Удалить спецификатор const из объявления конструктора А

Лучшее из этого - №3. Это лишит вас того, что, как я полагаю, является «гарантией», которая вам нужна: значение, используемое для инициализации объектов класса A, является постоянным. Чтобы добиться этого снова, вам придется использовать некоторую реализацию черт типа и шаблонных ограничений , чтобы гарантировать, что шаблон не может быть создан, когда T не является const типом.

2 голосов
/ 13 мая 2010

Я полагаю, это потому, что ваша функция ожидает const (char *) (так как T char *), т.е. вы не можете изменить адрес, на который она указывает, в то время как const char * означает (const char) *, т.е. вы не можете изменить значение на месте, на которое указывает указатель.

1 голос
/ 13 мая 2010

Если вы сделаете свой конструктор A(const char* _t), вы получите A( (const char) *t). То есть указатель на const char. Но когда вы указываете char* в качестве параметра шаблона, вы получаете A( const (char *t)) или постоянный указатель на символ.

Другими словами, я думаю, что у вас есть та же проблема, которая обсуждалась в статье Безумие летней ночи , за исключением параметров шаблона вместо typedefs.

1 голос
/ 13 мая 2010

Если вы удалите const перед присваиванием c, программа скомпилируется.

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

0 голосов
/ 13 мая 2010

Попробуйте преобразовать в const T &. Кроме того, в этих случаях вы должны позволить компилятору автоматически выводить аргумент шаблона, а не указывать его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...