views:

5529

answers:

3
+5  A: 

Use either just

original.to_string();

or, if you really need the type specifiers,

original.template to_string<char, char_traits<char>, allocator<char> >();
CAdaker
The to_string has no default specification in this case, but your latter answer works! Thanks.
cdleary
+2  A: 

The following compiled for me (using 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; 
}
Tim Stewart
Yeah, but it won't compile if you actually call the function and evaluate the template parameters.
cdleary
Adding #include <iostream> and changing main to this compiled (with gcc 4.0.1):int main(){ bitset<4> orig; orig.set(0,0); orig.set(1,1); orig.set(2,0); orig.set(3,1); bitset<2> bits = slice_bitset<2,4>(orig, 2); cout << bits.to_string() << endl; return 0;}What error are you getting?
Tim Stewart
I get the same error as above. I am using g++ 3.3, however -- they may have updated the stdlib in g++ to include a default template parameter in 3.4, but cplusplus.com says "they are not implicitly deduced by the compiler." (http://www.cplusplus.com/reference/stl/bitset/to_string.html)
cdleary
+6  A: 

The selected answer from CAdaker above 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;
};
Richard Corden