I'm looking for some code to make it work
template <typename T, int a, int b>
class first
{ //not so important
};
main()
{
first<double,1,2> sth;
second<double> sth2;
}
Sth2 is the same type as sth, but has default parameters (for example)
I do know I need some typedef. I tried
template <typename T>
struct help
{
typedef first<T,1,1> second;
};
but it works only with additional :: (help< double>::second) and i just want to change it for second< double>
Thank you for any ideas :)
You should just be able to define
template <typename T, int a=1, int b=2> class first
and then
first<double> sth2;
But if you really want two classes
template <typename T> class second : public first<T,1,1>
Should get you somewhere.
What about using default parameters? Otherwise igor might be right with C++11
Related
If I am allowed to do the following:
template <typename T = int>
class Foo{
};
Why am I not allowed to do the following in main?
Foo me;
But I must specify the following:
Foo<int> me;
C++11 introduced default template arguments and right now they are being elusive to my complete understanding.
Note:
Foo me; without template arguments is legal as of C++17. See this answer: https://stackoverflow.com/a/50970942/539997.
Original answer applicable before C++17:
You have to do:
Foo<> me;
The template arguments must be present but you can leave them empty.
Think of it like a function foo with a single default argument. The expression foo won't call it, but foo() will. The argument syntax must still be there. This is consistent with that.
With C++17, you can indeed.
This feature is called class template argument deduction and add more flexibility to the way you can declare variables of templated types.
So,
template <typename T = int>
class Foo{};
int main() {
Foo f;
}
is now legal C++ code.
You are not allowed to do that but you can do this
typedef Foo<> Fooo;
and then do
Fooo me;
You can use the following:
Foo<> me;
And have int be your template argument. The angular brackets are necessary and cannot be omitted.
Somewhat different case and rather later but where a template function is involved. gcc 11.2 can't seem to compile this:
template <typename T = int>
struct Test {};
template<typename T> void foo(T& bar) {}
int main()
{
Test t;
foo<Test>(t);
}
but has no problem with
template <typename T = int>
struct Test {};
template<typename T> void foo(T& bar) {}
int main()
{
Test t;
foo<Test<>>(t);
}
Of course
template <typename T = int>
struct Test {};
template<typename T> void foo(T& bar) {}
int main()
{
Test t;
foo(t);
}
works - but sometimes you need to explicitly force the type. Is this a compiler bug?
As per the C++17 Standard, template arguments are necessary to be passed.
But if you still want a way around this, you can use using keyword like this
template <typename T>
class Foo{
};
using IFoo=Foo<int>
Or, you can also use preprocessor like this
template <typename T>
class Foo{
};
#define IFoo Foo<int>
Quick Reminder
Preprocessors are bad for debugging.
I'm trying to create an alias to a template, rather than a type and I can't find the syntax to do it. Below is an example that demonstrates my problem. My guess is this is just something that can't be done, but I'm hoping someone can prove me wrong. If it can't be done, is there some underlying reason it doesn't make sense to do this, or is it just not implemented?
template <class S>
class Down;
template <class S>
class Up {
template <class S1>
using Opposite = Down<S1>;
};
template <class S>
class Down {
template <class S1>
using Opposite = Up<S1>;
};
template <template <typename> class Direction>
void oneDirection() {
//Call another function here that uses the template argument as a template
}
template <template <typename> class Direction>
void bothDirections() {
oneDirection<Direction>();
oneDirection<Direction::Opposite>(); //This doesn't compile
}
int main() {
bothDirections<Up>();
}
In Direction::Opposite, Direction:: is a nested-name-specifier, and it can't indeed denote a class template (you'd need to give it the required template arguments to make it a template specialization).
I suppose one reason to not allow that form is that class templates can have partial or explicit specializations, which can provide different members from the primary template, so the compiler needs to work with a specific specialization to be able to know exactly what's available in there.
You can work around this by using traits to associate the two templates:
template<class> class Up { };
template<class> class Down { };
template<template<class> class Direction> struct Direction_traits;
template<> struct Direction_traits<Up>
{
template<class S1> using Opposite = Down<S1>;
};
template<> struct Direction_traits<Down>
{
template<class S1> using Opposite = Up<S1>;
};
template<template<class> class Direction>
void oneDirection() {
//Do something here
}
template<template<class> class Direction>
void bothDirections() {
oneDirection<Direction>();
oneDirection<Direction_traits<Direction>::template Opposite>();
}
int main() {
bothDirections<Up>();
}
However, keep in mind that Direction_traits<Up>::Opposite is not the same template as Down, at least not yet - the language rules may change in the future, more details in this answer and its comments.
This could cause problems if you want to get back to Up from inside oneDirection<Direction_traits<Up>::Opposite> using the traits - there won't be a trait specialization defined for the alias template. Things would need to get a bit more complicated to allow such use; a possible solution is outlined in the answer quoted above.
I have come across such syntax:
template<typename>
struct is_const{static const bool value = 0;};
How will this code behave and how could it be applied? I didn't find any example or explanation in the Internet.
I am wondering about lack of the argument name (e.g. T).
This is a primary template which takes a single template argument and has a static bool member equal to 0. It is likely that this is the primary template definition for a type trait and that there is a corresponding specialization elsewhere which looks like this:
template <typename T>
struct is_const<const T>
{static const bool value = 1;};
This would allow you to check if a type is const qualified like so:
static_assert(!is_const<int>::value, "wat");
static_assert(is_const<const int>::value, "wat");
template <typename T>
class SampleClass
{
public:
T values [2];
SampleClass(T first, T second)
{
values[0]=first;
values[1]=second;
}
};
Try Something like this typename are generic way of programming. search for generic programming c++. You will get alot of resources
On a basic level of explanation, each time the template is used the compiler generates a version of the templated struct, class, function, etc.
for example:
template<typename T>
struct StructName
{
T memberVariable;
};
when this code is used:
StructName<float> variable = StructName<float>();
the compiler generates:
struct StructName
{
float memberVariable;
};
you can read more about this here: https://en.wikipedia.org/wiki/Template_metaprogramming
Given a template like
template<int dim> class Point { ... };
this template can be instantiated explicitly like
template class Point<0>;
template class Point<1>;
template class Point<2>;
template class Point<3>;
instead of instantiating every template individually like above, I would like to instantiate them recursively with one call like
template class RecursiveInstantiate<Point, 3>;
where RecursiveInstantiate<T, i> would instantiate T<i>, T<i-1>, ..., T<0>. Is it somehow possible to create such a class RecursiveInstantiate? If it is not possible, do you know a way to do it with the preprocessor?
In fact I am interested in generalizing this for classes with multiple template parameters likeNode<int i1,int i2,int i3> for all combination of i1,i2,i3 in {0,1,2,3}. But I hope to be able to work out this second part by myself.
Any advice, also an explanation why it is impossible what I want to achieve is appreciated.
Update: thank you for your comments so far. I see now more clearly where the problem really is. The line
template class Point<3>;
instantiates the template and exports its symbols to the object file. An instantiation of the form
template class RecursiveInstantiate<Point, 3>;
may instantiate the classes class Point<3>, class Point<2>, .... Apparently this only happens locally though. The templates are not exported to the object file. Maybe I will have to look for a solution using the preprocessor.
As I see now that I did not ask my question precisely enough in the beginning, I appreciate your answers and selected ones as correct.
Note: I am trying this on linux with g++/clang as compilers.
You could make a little Instantiator class:
template <unsigned int N> struct Instantiator
{
Point<N> p;
Instantiator<N-1> i;
};
template <> struct Instantiator<0>
{
Point<0> p;
};
Then simply add one explicit instantiation: template struct Instantiator<81>;
You can extend this idea lexicographically to any number of integral parameters.
As #Georg says, let's make it generic:
template <template <unsigned int> class T, unsigned int N> struct Instantiator
{
T<N> t;
Instantiator<T, N-1> i;
};
template <template <unsigned int> class T> struct Instantiator<T, 0>
{
T<0> t;
};
template struct Instantiator<Point, 82>;
You can do that like this:
template<int dim> struct Point {
static const int val = dim;
Point<dim - 1> p;
};
template<> struct Point<0> { ... };
That creates a template specialisation for the template parameter when it is 0 so the recursion stops there, and when you instantiate one like this:
Point<4>
It instantiates from Point<4> down to Point<0>. Then you can do
Point<4>::val
to access the value of that particular one.
If I have,
template<typename T1, typename T2, int N>
class X {};
Is there any way, that I can know class X has 3 template arguments ?
Use case in brief: There are two library classes ptr<T> (for normal pointer) and ptr_arr<T,N> (for pointer to array). These two are interacting with another class in following way:
template<typename T>
void Clear(const T &obj)
{
if(T::Args == 1) destroy(obj);
else destroy_arr(obj);
}
So, I thought if we have some handy way of knowing the number of parameters, it would make it easy. However, I learn that I need to change my business logic as there cannot be such way.
There is no standard way to do this (unless you use variadic sizeof(Args...) in C++0x) but that's beside the point -- the question is wrong.
Use overload resolution.
template <typename T>
void clear (ptr<T> & obj) {
destroy (obj);
}
template <typename T, int N>
void clear (ptr_arr<T,N> & obj) {
destroy_arr (obj);
}
You can use the mpl::template_arity (undocumented)
http://www.boost.org/doc/libs/1_40_0/boost/mpl/aux_/template_arity.hpp
There is no way to do this. Imagine the amount of overloads.
template<int> struct A;
template<bool> struct B;
template<char> struct C;
template<typename> struct D;
template<D<int>*> struct E;
template<D<bool>*> struct F;
template<typename, int> struct G;
// ...
For each of that, you would need a different template to accept them. You cannot even use C++0x's variadic templates, because template parameter packs only work on one parameter form and type (for example, int... only works for a parameter pack full of integers).