Can anyone help me with this code. I'm trying to specialise a method. At the moment it doesn't work with one specialisation (1) but I'd like to ultimately have lots of specialisations (2, 3, 4, 5 etc)
class X
{
public:
// declaration
template< int FLD >
void set_native( char *ptr, unsigned int length );
// specialisations
template<> void set_native< 1 >( char *ptr, unsigned int length )
{
}
};
The error messages I'm getting are..
x.cpp:13: error: explicit specialization in non-namespace scope 'class X'
x.cpp:13: error: template-id 'set_native<1>' for 'void set_native(char*, unsigned int)' does not match any template declaration
x.cpp:13: error: invalid function declaration
As Benoit proposed, you have to specialize the member function in the surrounding namespace:
struct X {
template<int N> void f() {}
};
template<> void X::f<1>() {} // explicit specialization at namespace scope
This is because of §14.7.3 (C++03):
An explicit specialization shall be declared in the namespace of which the template is a member, or, for member templates, in the namespace of which the enclosing class or enclosing class template is a member.
VC however doesn't conform to the standard in that regard and thus creates some portability headaches.
Try the following
class X
{
public:
// declaration
template< int FLD >
void set_native( char *ptr, unsigned int length );
};
// specialisations
template<> void X::set_native< 1 >( char *ptr, unsigned int length )
{
}
If it does not work, try adding a templated class behind set_native
template<int FLD> class SetNative;
class X
{
public:
// declaration
template< int FLD >
void set_native( char *ptr, unsigned int length )
{ return SetNative()(ptr, length); }
};
template<> class SetNative<1>
{
void operator()( char *ptr, unsigned int length ){...}
};
Related
Here is my unsuccessful attempt at detecting whether a free-standing function void set( T& , void (T::*Func)( const char* ) , const char* str ) exists for any class/struct T, in C++98/03.
#include <iostream>
#include <typeinfo>
struct Foo;
struct Bar;
struct Fuu;
void set( Foo& , void (Foo::*Func)( const char* ) , const char* str )
{
}
void set( Bar& , void (Bar::*Func)( const char* ) , const char* str )
{
}
template <typename T>
class setter_is_implemented
{
public:
typedef void (*SetterFunction)( T& , void (T::*)( const char* ) , const char* );
typedef char one;
typedef long two;
template <typename C> static one test( C c, SetterFunction = c ) ;
template <typename C> static two test(...);
public:
enum { value = sizeof( test<T>(&set)) == sizeof(one) };
};
int main()
{
std::cout << setter_is_implemented<Foo>::value << std::endl;
std::cout << setter_is_implemented<Bar>::value << std::endl;
std::cout << setter_is_implemented<Fuu>::value << std::endl;
}
GCC error message
Test.cpp:24:66: error: ‘c’ was not declared in this scope
template <typename C> static one test( C c, SetterFunction = c ) ;
^
Test.cpp: In instantiation of ‘class setter_is_implemented<Foo>’:
Test.cpp:33:44: required from here
Test.cpp:28:35: error: address of overloaded function with no contextual type information
enum { value = sizeof( test<T>(&set)) == sizeof(one) };
^
Test.cpp: In instantiation of ‘class setter_is_implemented<Bar>’:
Test.cpp:34:44: required from here
Test.cpp:28:35: error: address of overloaded function with no contextual type information
Test.cpp: In instantiation of ‘class setter_is_implemented<Fuu>’:
Test.cpp:35:44: required from here
Test.cpp:28:35: error: address of overloaded function with no contextual type information
AFAIK, taking the address of an overloaded function happens before overload resolution, so SFINAE cannot work in that way. This is also harder because your function returns void (otherwise, one would just check the size of the result ). My C++03 metaprogramming is rusty, but this should work (live on coliru):
namespace setter_is_implemented_detail {
struct dummy1 { char c[2]; };
typedef char dummy2;
dummy2 operator,(dummy1, dummy1);
template<typename T> dummy1 set(T const&,...);
template <typename T>
struct impl
{
typedef void (T::*FT)( const char* );
static T& x;
enum { value = sizeof( set(x,static_cast<FT>(0),static_cast<const char*>(0)), dummy1() ) != sizeof(dummy2) };
};
}
template <typename T>
struct setter_is_implemented: setter_is_implemented_detail::impl<T>{};
note a few things:
set() needs to be found by ADL here (not a big deal, as far as I can tell from your problem description)(*)
the comma operator trick(**) is needed due to the void return type; in gcc, you can take the sizeof(void), so the code can be simplified there
this won't work for non object types (due to the static T&). It can be made to work though, if you need so...
(*) Note that this cannot work for every possible set() overload; this is true for any sfinae, even in c++17, set() must always be sfinae-friendly in order to work.
If you need to match sfinae-friendly set() overloads exactly, it's still possible to do it, but it's more complex; I'd do it in two phases: first you use the above code to find possible candidates, then you check the function pointer conversion, somewhat like you do in your original code ..
(**) This trick works because if set() has void return type (and hence exists) the comma is always interpreted as the built-in comma operator (see c++03[3.9.1/9]: "An expression of type void shall be used only as an expression statement (6.2), as an operand of a comma expression[...]") resulting in the right-most expression. Otherwise, the dummy set and comma operator are used.
Sorry if this is such an easy question, there must be something I don't understand about inheritance, virtual and override in c++. In the following example, I get a compile-time error relative to a virtual method that I specifically override to avoid such error in a child class. Am I doing something wrong?
#include <array>
#include <deque>
template <class T, class C>
struct foo
{
virtual const C& data() const =0;
inline virtual T& operator[] ( unsigned n ) const
{ return const_cast<T&>( data()[n] ); }
};
/**
* The implementation of foo::operator[] is useful for classes inheriting
* with simple sequence containers like:
* foo<T,std::deque<T>>, foo<T,std::vector<T>>, ..
*
* But the following requires operator[] to be redefined:
*/
template <class T, unsigned N>
struct baz
: public foo<T, std::deque<std::array<T,N>> >
{
typedef std::deque<std::array<T,N>> data_type;
data_type m_data;
inline const data_type& data() const
{ return m_data; }
inline virtual T& operator[] ( unsigned n ) const override
{ return const_cast<T&>( data()[n/N][n%N] ); }
};
int main()
{
baz<double,3> b; // throws an error relative to foo::operator[] depsite override
}
EDIT 1 The error:
clang++ -std=c++0x -Wall virtual_operator.cpp -o virtual_operator.o
virtual_operator.cpp:11:12: error: const_cast from 'const value_type' (aka 'const std::__1::array<double, 3>') to 'double &' is not allowed
{ return const_cast<T&>( data()[n] ); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~
virtual_operator.cpp:26:8: note: in instantiation of member function 'foo<double, std::__1::deque<std::__1::array<double, 3>, std::__1::allocator<std::__1::array<double, 3> > > >::operator[]'
requested here
struct baz
^
1 error generated.
EDIT 2 I consider this to be part of the question; if compiling fails because foo::operator[] is still callable in baz, then why does it compile fine if I don't declare foo::operator[] as virtual (ie, hiding instead of overriding)?
The issue is that although you are only intending to call the derived operator[] function on baz instances, the compiler still needs to generate code for the base class because that function is still callable on baz instances. In this case, generating that code results in a type error, because you are trying to cast a const std::array<double,3> into a double&.
In order to fix this, you should have different parts of the hierarchy which define an operator which will work for all its children, like so (with non-pertainent stuff removed):
template <class T, class C>
struct foo
{
inline virtual T& operator[] ( unsigned n ) const = 0;
};
template <class T>
struct bar
: public foo<T,std::deque<T>>
{
inline virtual T& operator[] ( unsigned n ) const override
{ return const_cast<T&>( data()[n] ); }
};
template <class T, unsigned N>
struct baz
: public foo<T, std::deque<std::array<T,N>> >
{
inline virtual T& operator[] ( unsigned n ) const override
{ return const_cast<T&>( data()[n/N][n%N] ); }
};
This way if you have any other versions you want to add later, you can derive from bar or baz and not need to define the operator per-child.
I would like to have an array which has a length that depends on the parameter of my template, but I keep getting the "expected constant expression" error.
enum MyEnum
{
FIRST,
OTHER
};
template<MyEnum e>
struct MyTemplate
{
static const int arrSize;
int myArr[arrSize]; // error C2057: expected constant expression
// int myArr[e == FIRST ? 4 : 10]; // works, but isn't very readable...
};
template<>
const int MyTemplate<FIRST>::arrSize = 4;
template<>
const int MyTemplate<OTHER>::arrSize = 10;
The compiler I must use does not support constexpr, or any other C++ 11 features, and I also cannot pass the array size as a template parameter.
edit: I also must not use new.
Thanks
In some cases like this, I'll add a function get_array_size<e>(). Since you say you don't have constexpr, there's still decent possibilities:
//I call this a pseudo-template-function, but there's probably better names
template<MyEnum> struct GetArraySize; //compiler error for default
template<> struct GetArraySize<FIRST> {static const int value=4;};
template<> struct GetArraySize<OTHER> {static const int value=10;};
template<MyEnum e>
struct MyTemplate
{
static const int arrSize = GetArraySize<e>::value;
int myArr[arrSize];
};
http://coliru.stacked-crooked.com/a/f03a5fa94a038892
Are we reinventing the wheel here ? Enums are compile time constants. Just do this :
enum MyEnum
{
FIRST = 4,
OTHER = 10
};
template<MyEnum e>
struct MyTemplate
{
int myArr[e];
};
demo
I'm creating a trait class to help with my program. I have a template class called operations that contains the methods display and area. When I define these functions I get errors. Here they are:
error: specializing member ‘traits::operations<Rectangle>::display’ requires ‘template<>’ syntax
error: specializing member ‘traits::operations<Rectangle>::area’ requires ‘template<>’ syntax
As you can see, the compiler wants me to insert template <> just before those definitions. But when I do, I get a huge page of errors. What's going wrong and how can I fix it?
Here is my program.
namespace traits
{
template <typename P>
struct operations
{
static void display(Rectangle const &, std::ostream &);
static void area(Rectangle const &);
};
template <typename P, int N>
struct access {};
}
namespace traits
{
template <int N>
struct access<Rectangle, N>
{
static double get(Rectangle const &);
};
}
// The errors occur here
namespace traits
{
static void operations<Rectangle>::display(Rectangle const &rect, std::ostream &os)
{
os << rect.width << '\n';
os << rect.height << '\n';
os << area(rect) << '\n';
}
static void operations<Rectangle>::area(Rectangle const& rect)
{
double width = get<0>(rect);
double height = get<1>(rect);
return width * height;
}
}
namespace traits
{
template <>
struct access<Rectangle, 0>
{
static double get(Rectangle const &rect)
{
return rect.width;
}
};
template <>
struct access<Rectangle, 1>
{
static double get(Rectangle const &rect)
{
return rect.height;
}
};
}
template <int N, typename P>
static inline double get(P const &p)
{
return traits::access<P, N>::get(p);
}
template <typename P>
static inline void display(P const &p)
{
traits::operations<P>::display(p, std::cout);
}
template <typename P>
static inline double area(P const &p)
{
return traits::operations<P>::area(p);
}
int main()
{
}
Here is a program which shows the error - http://ideone.com/WFlnb2#view_edit_box
Any and all help is appreciated.
Thanks to help from the comments I got rid of those two errors, but I'm not getting more after adding the template<> declaration and fixing the return type of area:
error: cannot declare member function ‘static void traits::operations<P>::display(const Rectangle&, std::ostream&) [with P = Rectangle; std::ostream = std::basic_ostream<char>]’ to have static linkage [-fpermissive]
error: explicit template specialization cannot have a storage class
error: specialization of ‘static double traits::operations<P>::area(const Rectangle&) [with P = Rectangle]’ after instantiation
error: explicit template specialization cannot have a storage class
Your functions : display and area should be write like this:
template <>
double operations<Rectangle>::area( Rectangle const& rect )
{
double width = get<0>(rect);
double height = get<1>(rect);
return width * height;
}
As for template specialized functions, template <> should be placed
at the head of the function.
For static member functions, static should not appear at the
definition body of the function.
template< typename P > // P is declared here
struct operations {
... // into this scope
}; // but it goes out of scope here
template< typename P > // So it needs to be redeclared
void operations::display( Rectangle const &, std::ostream &) {
... // for this scope.
}
The function display doesn't "own" the names of its parameters. The template parameter must be redeclared in the definition. The compiler message is referring to template<> syntax to suggest you place something inside the <> brackets, but confusingly, leaving the brackets empty and literally saying template<> means something else — explicit specialization, which isn't what you want here.
On the other hand, static is a property of a member function which does not get mentioned in the definition. The compiler remembers static after using the other parts of the definition signature to match it to the declaration signature. So, you should erase static from the definition.
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;
}