C ++ два или более типов данных в объявлении

StackOverflow https://stackoverflow.com/questions/231868

  •  04-07-2019
  •  | 
  •  

Вопрос

Я получаю странную ошибку от g++ 3.3 в следующем коде:

#include <bitset>
#include <string>

using namespace std;

template <int N, int M>
bitset<N> slice_bitset(const bitset<M> &original, size_t start) {
    string str = original.to_string<char, char_traits<char>, allocator<char> >();
    string newstr = str.substr(start, N);
    return bitset<N>(newstr);
}

int main() {
    bitset<128> test;
    bitset<12> result = slice_bitset<12, 128>(test, 0);
    return 0;
}

Ошибка заключается в следующем:

In function `std::bitset slice_bitset(const std::bitset&, unsigned int)':
syntax error before `,' token
`char_traits' specified as declarator-id
two or more data types in declaration of `char_traits'
`allocator' specified as declarator-id
two or more data types in declaration of `allocator'
syntax error before `>' token

Это должно быть что-то действительно глупое, но я уже сказал это своей резиновой утке и другу безрезультатно.

Спасибо, Lazyweb.

Это было полезно?

Решение

Выбранный ответ из CAdaker выше решает проблема, но не объясняет почему это решает проблему.

При анализе шаблона функции поиск не выполняется в зависимых типах. В результате могут быть проанализированы такие конструкции, как следующие:

template <typename T>
class B;

template <typename T>
void foo (B<T> & b) {
  // Use 'b' here, even though 'B' not defined
}

template <typename T>
class B
{
  // Define 'B' here.
};

Тем не менее, это " функция " имеет стоимость, и в этом случае определение «foo» требует указаний на содержимое шаблона «B». Если в 'foo' используется вложенный тип 'B', ключевое слово typename требуется, чтобы сообщить компилятору, что это имя типа:

template <typename T>
void foo (B<T> & b)
{
  typename B<T>::X t1;    // 'X' is a type - this declares t1
  B<T>::Y * t1;           // 'Y' is an object - this is multiplication
}

Без 'typename' в приведенном выше, компилятор будет предполагать, что X является объектом (или функцией).

Аналогичным образом, если вызывается функция-член, и вызов имеет явные аргументы шаблона, то компилятору необходимо знать, что < следует рассматривать как начало списка аргументов шаблона, а не как оператор меньше:

template <typename T>
void foo (B<T> & b)
{
  b.template bar<int> (0); // 'bar' is a template, '<' is start of arg list
  b.Y < 10;                // 'Y' is an object, '<' is less than operator
}

Без template компилятор предполагает, что int> является оператором меньше чем, и поэтому генерирует синтаксическую ошибку, когда видит <=>, поскольку это не выражение.

Эти подсказки требуются даже , когда определение шаблона является видимым. Причина в том, что явная специализация может позже изменить фактически выбранное определение:

template <typename T>
class B
{
  template <typename S>
  void a();
};

template <typename T>
void foo (B<T> & b)
{
  b.a < 10;            // 'B<int>::a' is a member object
}

template <>
class B<int>
{
  int a;
};

Другие советы

Используйте либо просто

original.to_string();

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

original.template to_string<char, char_traits<char>, allocator<char> >();

Для меня скомпилировано следующее (с помощью gcc 3.4.4):

#include <bitset>
#include <string>

using namespace std;

template <int N, int M> 
bitset<N> slice_bitset(const bitset<M> &original, size_t start) 
{   
  string str = original.to_string();
  string newstr = str.substr(start, N);    
  return bitset<N>(newstr);
}

int main() 
{ 
  return 0; 
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top