As pointed out in the comments, my problem is actually:
template <typename T, typename U>
struct X {
static int i;
};
template <typename U>
int X<int, U>::i = 42;
with compiler error:
error: template definition of non-template 'int X<int, U>::i'
7 | int X<int, U>::i = 42;
How can I define this static member?
Original question below.
My use case is maybe a little odd:
#include <string>
#include <map>
#include <functional>
#include <memory>
template<typename ResourceType,
typename AllocatorType>
class ResourceManager
{
public:
typedef std::string IDType;
typedef std::shared_ptr<ResourceType> ResourceHandle;
typedef std::function<ResourceType(const IDType&, AllocatorType)> LoadFunc;
static ResourceHandle GetResource(const IDType& id, AllocatorType& alloc)
{
auto itr = m_resources.find(id);
if(itr != m_resources.end())
return itr->second;
ResourceHandle r
= std::make_shared<ResourceType>(m_loadFunc(id, alloc));
m_resources[id] = r;
return r;
}
static std::map<IDType, ResourceHandle> m_resources;
static LoadFunc m_loadFunc;
};
struct PretendAllocator
{
};
struct SomeResource
{
int i;
};
template<typename Allocator>
SomeResource load_some_resouce_from_file(const std::string& filename,
Allocator& alloc)
{
SomeResource x;
x.i = 12;
// let's pretend that the allocator was used and the filename was used
return x;
}
template<typename Allocator>
using SomeResourceManager = ResourceManager<SomeResource, Allocator>;
template<typename Allocator>
typename SomeResourceManager<Allocator>::LoadFunc
SomeResourceManager<Allocator>::m_loadFunc
= [](const SomeResourceManager<Allocator>::IDType& id,
Allocator& alloc)
{
return load_some_resouce_from_file(id, alloc);
}
int main()
{
// I don't know what kind of allocator I may have in real-world
PretendAllocator pretendAllocator;
// But I would use it to allocate a resource managed through Manager
SomeResourceManager<PretendAllocator>::ResourceHandle resource
= SomeResourceManager<PretendAllocator>::GetResource("some file",
pretendAllocator);
return 0;
}
This throws a bunch of compiler errors.
main.cpp|61|error: template definition of non-template 'typename ResourceManager<SomeResource, Allocator>::LoadFunc ResourceManager<SomeResource, Allocator>::m_loadFunc'|
main.cpp|62|error: invalid use of incomplete type 'SomeResourceManager<Allocator>'|
main.cpp|8|note: declaration of 'SomeResourceManager<Allocator>'|
main.cpp|68|error: expected ',' or '...' before 'int'|
main.cpp|77|error: expected ')' at end of input|
main.cpp|62|note: to match this '('|
main.cpp|77|error: expected '{' at end of input|
My use case is that I would have multiple resources which are expensive to load/acquire. So the ResourceManager has some code around it that will only call the static std::function members when absolutely required (real-world is more complex than this example).
The above seemed like the best way to do this. Basically, when defining a Resource, you would also create an alias for a ResourceManager<YourResource> but I now have the added complexity of needing to include an Allocator.
How can I get the above to compile? I'm not sure exactly what the problem is. If it's not possible, would be great to hear an alternative.
You cannot partially specialise a member without partially specialising the entire class.
Insert a partial specialisation
template <typename U>
struct X<int, U> {
static int i;
};
before the definition of i and it should work.
Related
I try to do partial specialisation for a template function where the specialized type T might also be a class template. However the following Code does not work.
#include <iostream>
#include <vector>
template <class T>
constexpr T neutral();
template <>
constexpr int neutral() { return 0; } // Okay. This is how partial specialisation works.
template <class U>
constexpr std::vector<U> neutral() { return std::vector<U>{ neutral<U>() }; }
int main()
{
const auto n{ neutral<std::vector<int>>() }; // error
}
main.cpp:16:19: error: call to 'neutral' is ambiguous
const auto n{ neutral<std::vector<int>>() }; // error
^~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:5:13: note: candidate function [with T = std::vector<int, std::allocator<int> >]
constexpr T neutral();
^
main.cpp:11:26: note: candidate function [with U = std::vector<int, std::allocator<int> >]
constexpr std::vector<U> neutral() { return std::vector<U>{ neutral<U>() }; } //error
^
My design goal is as follows: I provide an algorithm that can take any type that any programmer wants to use as long as he defines what the so called natural<T>() of his type T is. (However my actual code looks differently. This is a minimalistic example I tried to extract.)
How can it be implemented correctly?
I first thought, it must be something like
template <>
template <class U>
constexpr std::vector<U> neutral<std::vector<U>>() { return std::vector<U>{ neutral<U>() }; } //error
But this also ends up in errors:
main.cpp:11:26: error: function template partial specialization is not allowed
constexpr std::vector<U> neutral<std::vector<U>>() { return std::vector<U>{ neutral<U>() }; } //error
^ ~~~~~~~~~~~~~~~~
EDIT:
The context I want to use it is like this...
I have some class class Z7 which is representing a (math.) ring. I want to use something like the neutral in the example for the zero and the one element of the ring. Then there is a class
template <class _Ring>
class polynomial;
which will represent polynoms over the ring _Ring, e.g., 2x^5 + x^3 + 4x + 1. Therefore, polynomial<_Ring> will also be a ring whenever _Ring has been a ring. Thus I want to define a template specialisation for a zero and a one for polynomial<_Ring> by using the zero and one of type _Ring.
Functions need a difference in their parameters to have different definitions, classes/structs can be specialized without such a constraint, perhaps what you're looking for is closer to...
#include <vector>
template <typename T>
struct neutral;
template <typename T>
struct neutral {
static constexpr int get() { return 0; }
};
template <typename T>
struct neutral<std::vector<T>> {
static constexpr std::vector<T> get() { return std::vector<T>(); }
};
int main()
{
const auto n{ neutral<std::vector<int>>::get() };
const auto m{ neutral<float>::get() };
}
The standard says the following about specializing templates from the standard library (via What can and can't I specialize in the std namespace? )
A program may add a template
specialization for any standard library template to namespace std only
if the declaration depends on a user-defined type and the
specialization meets the standard library requirements for the
original template and is not explicitly prohibited.
Is it legal to specialize standard library templates with a standard library class specialized with a user defined class?
For example, specializing std::hash for std::shared_ptr<MyType>?
From reading the above paragraph and linked question, it sounds like it should be, as the declaration of the specialization is dependent on MyType, however "Unless explicitly prohibited" worries me slightly.
The example below compiles and works as expected (AppleClang 7.3), but is it legal?
#include <unordered_set>
#include <memory>
#include <cassert>
#include <string>
struct MyType {
MyType(std::string id) : id(id) {}
std::string id;
};
namespace std {
template<>
struct hash<shared_ptr<MyType>> {
size_t operator()(shared_ptr<MyType> const& mine) const {
return hash<string>()(mine->id);
}
};
template<>
struct equal_to<shared_ptr<MyType>> {
bool operator()(shared_ptr<MyType> const& lhs, shared_ptr<MyType> const& rhs ) const {
return lhs->id == rhs->id;
}
};
}
int main() {
std::unordered_set<std::shared_ptr<MyType>> mySet;
auto resultA = mySet.emplace(std::make_shared<MyType>("A"));
auto resultB = mySet.emplace(std::make_shared<MyType>("B"));
auto resultA2 = mySet.emplace(std::make_shared<MyType>("A"));
assert(resultA.second);
assert(resultB.second);
assert(!resultA2.second);
}
Yes, that is legal.
It is even questionably legal to specialize for std::shared_ptr<int> at one point; I don't know if they patched that ambiguity in the standard as a defect or not.
Note that that is a poor implemenation of a hash for global use. First, because it doesn't support null shared pointers. Second, because hashing a shared pointer as always the int value is questionable. It is even dangerous, because if a shared pointer to an int in a container has that int change, you just broke the program.
Consider making your own hasher for these kind of cases.
namespace notstd {
template<class T, class=void>
struct hasher_impl:std::hash<T>{};
namespace adl_helper {
template<class T>
std::size_t hash( T const& t, ... ) {
return ::notstd::hasher_impl<T>{}(t);
}
};
namespace adl_helper2 {
template<class T>
std::size_t hash_helper(T const& t) {
using ::notstd::adl_helper::hash;
return hash(t);
}
}
template<class T>
std::size_t hash(T const& t) {
return ::notstd::adl_helper2::hash_helper(t);
}
struct hasher {
template<class T>
std::size_t operator()(T const& t)const {
return hash(t);
}
};
}
Now this permits 3 points of customization.
First, if you override std::size_t hash(T const&) in the namespace containing T, it picks it up.
Failing that, if you specialize notstd::hasher_impl<T, void> for your type T, it picks it up.
Third, if both of those fail, it invokes std::hash<T>, picking up any specializations.
Then you can do:
std::unordered_set<std::shared_ptr<MyType>, ::notstd::hasher> mySet;
and add:
struct MyType {
MyType(std::string id) : id(id) {}
std::string id;
friend std::size_t hash( MyType const& self) {
return ::notstd::hash(self.id);
}
friend std::size_t hash( std::shared_ptr<MyType> const& self) {
if (!self) return 0;
return ::notstd::hash(*self);
}
};
which should give you a smart hash on on shared_ptr<MyType>.
This keeps the danger that someone changes id on a shared_ptr<MyType> which breaks every container containing the shared_ptr<MyType> in a non-local manner.
Shared state is the devil; consider writing a copy on write pointer if you are really worried about copying these things being expensive.
I am trying to write a template class which may or may not define a particular member function depending on its template parameter type. Further the return type of this member function depends on the return type of of a member of the template paramter (if defined).
Below is a minimal example of my code
#include <iostream>
#include <type_traits>
template <typename T>
struct has_foo_int {
private:
template <typename U>
static decltype(std::declval<U>().foo(0), void(), std::true_type()) test(int);
template <typename>
static std::false_type test(...);
public:
typedef decltype(test<T>(0)) test_type;
enum { value = test_type::value };
};
template <typename T, bool HasFooInt>
struct foo_int_return_type;
template<typename T>
struct foo_int_return_type<T,false> {};
template<typename T>
struct foo_int_return_type<T,true> {
using type = decltype(std::declval<T>().foo(0));
};
template<typename T>
struct mystruct
{
T val;
//auto someMethod(int i) -> decltype(std::declval<T>().foo(0)) // error: request for member ‘foo’ in ‘std::declval<double>()’, which is of non-class type ‘double’
//auto someMethod(int i) -> typename foo_int_return_type<T,has_foo_int<T>::value>::type // error: no type named ‘type’ in ‘struct foo_int_return_type<double, false>’
template<typename R=typename foo_int_return_type<T,has_foo_int<T>::value>::type> R someMethod(int i) // error: no type named ‘type’ in ‘struct foo_int_return_type<double, false>’
{
return val.foo(i);
}
};
struct with_foo_int {
int foo(int i){
return i+1;
}
};
using namespace std;
int main(void)
{
mystruct<with_foo_int> ms1;
cout << ms1.someMethod(41) << endl;
mystruct<double> ms2;
return 0;
}
What I would like to happen is that the code compiles fine and outputs 42 for ms1.someFunc(41). I would also expect that if one accidentally tried to call someFunc on ms2 that it would fail to compile.
Unfortunately each of the alternatives I have tried has failed. The first and second, I think I understand why they wouldn't work.
I read here that SFINAE only works for template functions so I tried giving a dummy template parameter to work out the return type but this too fails in the same way.
I'm clearly not understanding something here, what am I missing? Is it possible to achieve what I'm trying to do?
Thanks.
P.s. I'm using g++ 4.7.3
P.p.s I have also tried std::enable_if but get much the same results as with my foo_int_return_type struct.
Here is a short, tidy and documented way of doing what you are attempting,
with some possible bugs addressed thereafter.
#include <type_traits>
/*
Template `has_mf_foo_accepts_int_returns_int<T>`
has a static boolean public member `value` that == true
if and only if `T` is a class type that has a public
member function or member function overload
`int T::foo(ArgType) [const]` where `ArgType`
is a type to which `int` is implicitly convertible.
*/
template <typename T>
struct has_mf_foo_accepts_int_returns_int {
/* SFINAE success:
We know now here `int *` is convertible to
"pointer to return-type of T::foo(0)"
*/
template<typename A>
static constexpr bool test(
decltype(std::declval<A>().foo(0)) *prt) {
/* Yes, but is the return-type of `T::foo(0)`
actually *the same* as `int`?...
*/
return std::is_same<int *,decltype(prt)>::value;
}
// SFINAE failure :(
template <typename A>
static constexpr bool test(...) {
return false;
}
/* SFINAE probe.
Can we convert `(int *)nullptr to
"pointer to the return type of T::foo(0)"?
*/
static const bool value = test<T>(static_cast<int *>(nullptr));
};
template<typename T>
struct mystruct
{
using has_good_foo = has_mf_foo_accepts_int_returns_int<T>;
T val;
/* SFINAE:
`template<typename R> R someMethod(R)` will be this if and only
if `R` == `int` and `has_good_foo` == true.
*/
template<typename R = int>
typename std::enable_if<
(has_good_foo::value && std::is_same<R,int>::value),R
>::type
someMethod(R i) {
return val.foo(i);
}
/* SFINAE:
`template<typename R> R someMethod(R)` will be this if and only
if `R` != `int` or `has_good_foo` != true.
*/
template<typename R = int>
typename std::enable_if<
!(has_good_foo::value && std::is_same<R,int>::value),R
>::type
someMethod(R i) {
static_assert(has_good_foo::value && std::is_same<R,int>::value,
"mystruct<T> does not implement someMethod(R)");
return i;
}
};
// Testing...
#include <iostream>
struct with_foo_int
{
int foo(int i) {
return i + 1;
}
};
using namespace std;
int main(void)
{
mystruct<with_foo_int> ms1;
cout << ms1.someMethod(41) << endl;
mystruct<double> ms2;
cout << ms2.someMethod(41) << endl; // static_assert failure
return 0;
}
This solution faithfully reproduces a couple of possible loopholes in your
own attempt as posted:-
1) It looks as if you may believe that evaluating std::declval<U>().foo(0) is
a SFINAE way of determining whether U::foo exists and takes a single argument
of type int. It doesn't. It is merely a SFINAE way of determining whether
U::foo(ArgType) exists where ArgType is anything to which 0 is
implicitly convertible. Thus ArgType could be any pointer-or-arithmetic
type, not just int.
2) You may not have considered that std::declval<U>().foo(0) will be satisfied
if either or both of U::foo(ArgType) U::foo(ArgType) const exists. You
may well care whether you call a const or a non-const member function on
U, and you would certainly care which of two member function you call. If
with_foo_int were defined as:
struct with_foo_int
{
int foo(int i) const {
return i + 1;
}
int foo(int i) {
return i + 2;
}
};
then the solution given would call the non-const overload and
ms1.someMethod(41) would == 43.
2) Is easily dealt with. If you wish to ensure that you can only call
T::foo(ArgType) const then add a const qualifier to mystruct::someMethod.
If you don't care or wish only to call T::foo(ArgType) then leave things
as they are.
1) is a little harder to solve, because you must craft a SNIFAE probe for
T::foo that is satisfied only if it has the right signature, and that
signature will either be const qualified or not. Let's assume you want
int T::foo(int) const. In that case, replace template
has_mf_foo_accepts_int_returns_int with:
/* Template `has_mf_foo_arg_int_returns_int<T>
has a static boolean public member `value` that == true
if and only if `T` is a class type that has an un-overloaded
a public member `int T::foo(int) const`.
*/
template< typename T>
struct has_mf_foo_arg_int_returns_int
{
/* SFINAE foo-has-correct-sig :) */
template<typename A>
static std::true_type test(int (A::*)(int) const) {
return std::true_type();
}
/* SFINAE foo-exists :) */
template <typename A>
static decltype(test(&A::foo))
test(decltype(&A::foo),void *) {
/* foo exists. What about sig? */
typedef decltype(test(&A::foo)) return_type;
return return_type();
}
/* SFINAE game over :( */
template<typename A>
static std::false_type test(...) {
return std::false_type();
}
/* This will be either `std::true_type` or `std::false_type` */
typedef decltype(test<T>(0,0)) type;
static const bool value = type::value; /* Which is it? */
};
and in template mystruct replace:
using has_good_foo = has_mf_foo_accepts_int_returns_int<T>;
with:
using has_good_foo = has_mf_foo_arg_int_returns_int<T>;
(Template has_mf_foo_arg_int_returns_int is adapted
from my other answer and
you can read how it works there.)
What you gain in SFINAE-precision from the latter approach comes at
a price. The approach requires you to attempt to take the address of T::foo,
to see if it exists. But C++ will not give you the address of an overloaded
member function, so this approach will fail if T::foo is overloaded.
The code here will compile (or appropriately static_assert) with
GCC >= 4.7.2 clang >= 3.2.
I'd like to hide a std::tuple in my class 'Record' and provide an operator[] on it to access elements of the tuple. The naive code that does not compile is this:
#include <tuple>
template <typename... Fields>
class Record {
private:
std::tuple<Fields...> list;
public:
Record() {}
auto operator[](std::size_t n)
-> decltype(std::get<1u>(list)) {
return std::get<n>(list);
}
};
int main() {
Record<int, double> r;
r[0];
return 0;
}
g++ 4.6 says:
x.cc:13:32: error: no matching function for call to ‘get(std::tuple<int, double>&)’
x.cc:13:32: note: candidates are:
/usr/include/c++/4.6/utility:133:5: note: template<unsigned int _Int, class _Tp1, class _Tp2> typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(std::pair<_Tp1, _Tp2>&)
/usr/include/c++/4.6/utility:138:5: note: template<unsigned int _Int, class _Tp1, class _Tp2> const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(const std::pair<_Tp1, _Tp2>&)
/usr/include/c++/4.6/tuple:531:5: note: template<unsigned int __i, class ... _Elements> typename std::__add_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(std::tuple<_Elements ...>&)
/usr/include/c++/4.6/tuple:538:5: note: template<unsigned int __i, class ... _Elements> typename std::__add_c_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(const std::tuple<_Elements ...>&)
Basically I'd like to call Record::operator[] just like on an array. is this possible?
The argument to get is a compile time constant. You cannot use a
runtime variable for this and you cannot have a single function that
returns the tuple members as your return type is going to be
wrong. What you can do is to abuse non-type argument deduction:
#include <tuple>
template<typename... Args>
struct Foo {
std::tuple<Args...> t;
template<typename T, std::size_t i>
auto operator[](T (&)[i]) -> decltype(std::get<i>(t)) {
return std::get<i>(t);
}
// also a const version
};
int main()
{
Foo<int, double> f;
int b[1];
f[b];
return 0;
}
This is so horrible, that I would never use it and it won't make much sense to users. I would just forward get through a template member.
I'll try to explain why I think why this is really evil: The return type of a function depends only on compile time facts (this changes slightly for virtual member functions). Let's just assume that non-type argument deduction were possible for some cases (the function call arguments are constexpr) or that we could build something that hides it reasonably well, your users wouldn't realize that their return type just changed and implicit conversion would do nasty things to them. Making this explicit safes some of the trouble.
The error message seems to be misleading, as the problem with your code is pretty much clear:
auto operator[](std::size_t n)
-> decltype(std::get<1u>(list)) {
return std::get<n>(list);
}
The template argument n to std::get must be a constant expression, but in your code above n is not a constant expression.
No.
It is not possible to use a parameter bound at runtime (such as a function parameter) to act as template parameter, because such need be bound at compile-time.
But let's imagine for a second that it was:
Record<Apple, Orange> fruitBasket;
Then we would have:
decltype(fruitBasket[0]) equals Apple
decltype(fruitBasket[1]) equals Orange
is there not something here that bothers you ?
In C++, a function signature is defined by the types of its arguments (and optionally the values of its template parameters). The return type is not considered and does not participate (for better or worse) in the overload resolution.
Therefore, the function you are attempting to build simply does not make sense.
Now, you have two alternatives:
require that all arguments inherit or be convertible to a common type, and return that type (which allows you to propose a non-template function)
embrace templates and require your users to provide specifically the index of the type they wish to use
I do not (and cannot) which alternative is preferable in your particular situation, this is a design choice you will have to make.
Finally, I will remark that you may be reasoning at a too low level. Will your users really need to access each field independently ? If they don't, you could provide facilities to apply functions (visitors ?) to each element in turn, for example.
I think Xeo had code which did this.
Here is my attempt which somewhat works. The problem is that [] is not a reference.
template<typename T, std::size_t N = std::tuple_size<T>::value - 1>
struct foo {
static inline auto bar(std::size_t n, const T& list)
-> decltype(((n != N) ? foo<T, N-1>::bar(n, list) : std::get<N>(list))) {
return ((n != N) ? foo<T, N-1>::bar(n, list) : std::get<N>(list));
}
};
template<typename T>
struct foo<T, 0> {
static inline auto bar(std::size_t n, const T& list)
-> decltype(std::get<0>(list)) {
return std::get<0>(list);
}
};
template <typename... Fields>
class Record {
private:
std::tuple<Fields...> list;
public:
Record() {
std::get<0>(list) = 5;
}
inline auto operator[](std::size_t n)
-> decltype(foo<decltype(list)>::bar(n, list)) {
return foo<decltype(list)>::bar(n, list);
}
};
int main() {
Record<int, double> r;
std::cout << r[0];
return 0;
}
As n is a template parameter, it should be known in compile time, but you want to pass it as a parameter in run-time.
Also, gcc 4.5.2 isn't happy due to this fact:
g++ 1.cpp -std=c++0x
1.cpp: In member function 'decltype (get<1u>(((Record<Fields>*)0)->Record<Fields>::list)) Record<Fields>::operator[](size_t)':
1.cpp:14:25: error: 'n' cannot appear in a constant-expression
If you're fine with a compile-time constant and still want to have the nice operator[] syntax, this is an interesting workaround:
#include <tuple>
template<unsigned I>
struct static_index{
static unsigned const value = I;
};
template <typename... Fields>
class Record {
private:
typedef std::tuple<Fields...> tuple_t;
tuple_t list;
public:
Record() {}
template<unsigned I>
auto operator[](static_index<I>)
-> typename std::tuple_element<
I, tuple_t>::type&
{
return std::get<I>(list);
}
};
namespace idx{
const static_index<0> _0 = {};
const static_index<1> _1 = {};
const static_index<2> _2 = {};
const static_index<3> _3 = {};
const static_index<4> _4 = {};
}
int main() {
Record<int, double> r;
r[idx::_0];
return 0;
}
Live example on Ideone. Though I'd personally just advise to do this:
// member template
template<unsigned I>
auto get()
-> typename std::tuple_element<
I, tuple_t>::type&
{
return std::get<I>(list);
}
// free function
template<unsigned I, class... Fields>
auto get(Record<Fields...>& r)
-> decltype(r.template get<I>())
{
return r.template get<I>();
}
Live example on Ideone.
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.
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;
};
Use either just
original.to_string();
or, if you really need the type specifiers,
original.template to_string<char, char_traits<char>, allocator<char> >();
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;
}