Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ two or more data types in declaration

Tags:

c++

templates

g++

I'm getting a strange error from g++ 3.3 in the following code:

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

The error is as follows:

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

It has to be something really silly, but I've already told it to my rubber duck and a friend to no avail.

Thanks, Lazyweb.

like image 723
cdleary Avatar asked Oct 23 '08 22:10

cdleary


1 Answers

The selected answer from CAdaker solves the problem, but does not explain why it solves the problem.

When a function template is being parsed, lookup does not take place in dependent types. As a result, constructs such as the following can be parsed:

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

However, this "feature" has a cost, and in this case it is that the definition of 'foo' requires hints on the contents of the template 'B'. If 'foo' uses a nested type of 'B', then the typename keyword is required to tell the compiler that the name is a type:

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
}

Without 'typename' in the above the compiler will assume that X is an object (or function).

Similarly, if a member function is called and the call has explicit template arguments then the compiler needs to know to treat the < as the start of a template argument list and not the less than operator:

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
}

Without template, the compiler assumes that < is the less than operator, and so generates the syntax error when it sees int> since that is not an expression.

These hints are required even when the definition of the template is visible. The reason is that an explicit specialization might later change the definition that is actually chosen:

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;
};
like image 177
Richard Corden Avatar answered Sep 21 '22 12:09

Richard Corden