using c++ language : i made a structure generic and i want to give it an alias but failed !
here is the code:
template<class T>
struct noeud {
T val;
struct noeud *next;
};
typedef struct noeud * Noeud;
here is the error:
template argument required for 'struct noeud'
invalid type in declaration before ';' token
Build : 2 error(s), 0 warning(s)
you can achieve this by using a syntax introduced in the C++11 revision :
template<class T>
struct Node;
template <class T>
using NodePtr = Node<T>*;
You should stay away from naked pointer and use a smart pointer instead, like unique_ptr :
template <class T>
using NodePtr = std::unique_ptr<Node<T>>;
it should be
typedef struct noeud<your type>* Noeud;
where your type is the type you want the struct to be instanciated with
If you want to have another template as an alias you have to use the using keyword:
template<typename T>
using AliasName = noeud<T>*;
To add to the other answers:
The class noeud is a template and thus it needs a template parameter to become a type as template types are deduced at compile time. E.g.:
template<class T>
struct noeud {
T val;
//noeud* next // Error: compiler doesn't know what a noeud is.
noeud<T>* next; // Need to specify template parameter (T can be used).
};
typedef noeud<int>* Noeud; // Need to specify template parameter.
Also in C++ you don't have to put the keyword struct in front of the type when declaring "structs"/aggregate classes when there is no ambiguity. In C++ the keyword struct means class with default access specifier set to public.
As mentioned by others, in C++11 you can use the using syntax to declare a templated alias (typedef does not allow templated aliases), e.g.:
template<typename T>
using noeud<T>* Noeud; // Use 'using' to create an alias in same manner as typedef.
This allows you to use the alias as:
Noeud<int> n; // Type is: noeud<int>*
Related
I'm trying to implement the following code, but I keep getting an error because of typedef, can someone please help?
template<class T>
struct box{
T data;
box *link;
};
typedef box* boxPtr;
the error is:
Use of class template 'box' requires template arguments
box is a class template. This means that it needs an argument whenever you instantiate it:
box<int> integerBox;
box<float> floatBox;
// etc
This is required anywhere you try to use a template class such as box. So a pointer to just a box doesn't make sense. It needs a type with it. For example:
template <class type>
using boxptr = box<type>*;
This does effectively the same thing as your typedef, but it allows you to specify he underlying template type.
Of course, if you do it this way, you will always need to specify a type when you use the pointer version:
boxptr<int> integerBoxPtr;
boxptr<float> floatBoxPtr;
// etc
Writing
template<class T>
struct box{
T data;
box *link;
typedef box<T>* boxPtr;
};
with
int main()
{
box<int>::boxPtr use_of_a_bad_idea;
}
is one way, but having pointer types masquerading as object types is a recipe for memory leaks: don't do it as a rule of thumb. That's the best way of addressing this problem.
Use using:
template<class T>
struct box
{
T data;
box *link;
};
template <typename T>
using boxPtr = box<T>*;
Now boxPtr<int> is the same as box<int>*.
This will compile:
template<class T>
struct Box {
T data;
Box<T> *link;
};
typedef Box<int> * BoxPTR;
For a template class
template<typename T>
class node{
public:
static auto null_node_type = typename //shared pointer holding node<T>*
// cast from NULL
};
I would like to include a type declaration as above within the template definition, but not sure how to achieve this.
I tried the following, which didn't work:
1. static auto null_node_type =
typename shared_ptr<reinterpret_cast<node<T>*>(NULL)>;
In this case, the compiler complains that the shared_ptr<> template expects a type.
2. std::function<shared_ptr<T>(T)> make_null_obj_type = [] (T arg){
return(make_shared<arg>(NULL));
};
template<typename T>
class node{
public:
static auto null_node_type = make_null_obj_type<node<T>>;
};
In this case, the compiler flags the error that node<T> (wherein T is substituted by the actual template argument) is not a complete object type.
What is the correct way to achieve this?
I want to use a pointer to a class member as a template parameter as in:
template <class Class, class Result, Result Class::*Member>
struct MyStruct {
// ...
};
Using this struct like MyStruct<SomeClass, SomeResult, &SomeClass::value> variable works just fine, but I don't like that I have to specify SomeClass and SomeResult.
I would like to use MyStruct<&SomeClass::value> variable if that is possible, but without losing the ability to pass any class and have any result type.
I tried the following, but the syntax is illegal:
template <class Class, class Result>
template <Result Class::*Member>
struct MyStruct {
// ...
};
error: too many template-parameter-lists
I tried using a helper function (that does actually work in Clang but is refused by GCC):
template <class Class, class Result>
static constexpr auto makeMyStruct(Result Class::*member) ->
MyStruct<Class, Result, member> {
// ...
}
error: use of parameter `member' outside function body
error: template argument 3 is invalid
Is it possible to have a simple MyStruct<&SomeClass::value>, and if so, how?
Related question that did not solve my question:
Pointer to class member as template parameter
C++0x error with constexpr and returning template function
In c++17, with the addition of auto in template arguments (P0127), I think you can now do:
template<auto value>
struct MyStruct {};
template<typename Class, typename Result, Result Class::* value>
struct MyStruct<value> {
// add members using Class, Result, and value here
using containing_type = Class;
};
typename MyStruct<&Something::theotherthing>::containing_type x = Something();
An answer to my question was proposed in this paper for the next upcoming C++ standard:
https://isocpp.org/files/papers/n3601.html
This syntax was proposed:
template<using typename T, T t>
struct some_struct { /* ... */ };
some_struct<&A::f> x;
The need for a new syntactical construct indicates that you cannot do that by now.
I hope n3601 will be accepted. :-)
This could be a solution in C++11:
You can define the following generic type traits:
template<class T>
struct remove_member_pointer {
typedef T type;
};
template<class Parent, class T>
struct remove_member_pointer<T Parent::*> {
typedef T type;
};
template<class T>
struct baseof_member_pointer {
typedef T type;
};
template<class Parent, class T>
struct baseof_member_pointer<T Parent::*> {
typedef Parent type;
};
Now you can define an additional, 4-line wrapper macro for every struct:
template<class Class, class Result, Result Class::*Member>
struct _MyStruct {
// ...
};
#define MyStruct(MemberPtr) \
_MyStruct<baseof_member_pointer<decltype(MemberPtr)>::type, \
remove_member_pointer<decltype(MemberPtr)>::type, \
MemberPtr>
... and use it in the following way:
MyStruct(&SomeClass::value) myStruct; // <-- object of type MyStruct<&SomeClass:value>
I use this as an intermediate solution, until we switch to C++17.
Make your result class a child of your template class. assuming the pointer member is an object of your result class in public or whatever, you can access any objects by doing something like this
template <stuff for this class> :: public result
{
blah
}
I'm trying to implement the pointer to implementation pattern with template classes, and, in order to make independent class and its implementation, I use the next approach:
template<typename T>
struct __A_impl;
template<typename T>
struct A
{
using __impl_t = __A_impl<T>;
A(__impl_t* t);
__impl_t* _t;
};
template<typename T>
struct B
{
T _t;
};
template<typename T>
using __A_impl = B<T>;
With this form, if I want to change the name of 'B', this doens't affect in any way the definition of A. But, I receive the next error with gcc:
test.cpp:21:22: error: declaration of template 'template<class T> using __A_impl = B<T>'
test.cpp:2:7: error: conflicts with previous declaration 'template<class T> class __A_impl'
test.cpp:21:22: error: redeclaration of 'template<class T> using __A_impl = B<T>'
test.cpp:2:7: note: previous declaration 'template<class T> class __A_impl'
How can I achieve this? Because with a typedef declarator isn't possible.
You cannot forward declare a typedef. You can only forward declare classes/structs/enums.
Also, PIMPL is usually used to prevent the compiler from seeing the implementation, but in your case that's never going to happen because it's a template, so I don't see the point.
Well, this compiles, although it might not be what you want:
template<typename T>
struct B
{
T _t;
};
template<typename T>
using __A_impl = B<T>;
template<typename T>
struct A
{
using __impl_t = __A_impl<T>;
A(__impl_t* t);
__impl_t* _t;
};
Anyway, two things:
Why not just use std::unique_ptr?
Double underscores are reserved for implementation. Don't use them.
template <typename vec1, typename vec2>
class fakevector
{
public:
/* Do something */
};
template <class A>
class caller
{
public:
struct typeList
{
struct typeOne
{
//...
};
};
typedef fakevector<typeList::typeOne,int> __methodList; /* This will trigger compile error */
};
The error messages I got are:
Error: type/value mismatch at
argument 1 in template parameter
list for ‘template class fakevector’
Error: expected a type, got ‘caller::typeList::typeOne’
If template is removed from the caller class, no error will be reported,
like this
class caller
{
public:
struct typeList
{ ....
};
I don't know the reason. Thank you very much!
Try:
typedef fakevector<typename typeList::typeOne,int> __methodList;
http://www.comeaucomputing.com/techtalk/templates/#typename
Looks like the compiler is in doubt what typeOne is.
typedef fakevector<typename typeList::typeOne,int>
should compile
Try typedef fakevector<typename typeList::typeOne,int>
The typename prefix to a name is required when the name
Appears in a template
Is qualified
Is not used as in a list of base class specifications or in a list of member initializers introducing a constructor definition
Is dependent on a template parameter
Furthermore, the typename prefix is not allowed unless at least the first three previous conditions hold.