default template parameters

P

Patrick Kowalzick

Dear all,

I have a question about default template parameters.

I want to have a second template parameter which as a default parameter,
but depends on the first one (see below). Is something like that possible?
Some workaround?

Thank you,
Patrick


// Definitions
template <typename T1=int,typename T2=int> class foo;
// this is not working (sure):
template <double, typename T2=double> class foo;

// Implementation
template <typename T1,typename T2> class foo{};



int main()
{
foo<> a1; // foo class <int,int>
foo<int> a2; // foo class <int,int>
foo<float> a3; // foo class <float,int>
foo<float,float> c; // foo class <float,float>

// BUT this should be defined via second definition:
foo<double> b; // foo class <double,double>

return 0;
}
 
C

Clemens Auer

// Definitions
template <typename T1=int,typename T2=int> class foo;

tryed something like:
template <typename T1=int,typename T2=T1> class foo;
???

i don't know if it works ... !!
 
P

Patrick Kowalzick

Hi Clemens,
tryed something like:
template <typename T1=int,typename T2=T1> class foo;
???

i don't know if it works ... !!

No, it is not working. Please regard a3 with one float. This would be
<float,float> as well.

foo<int> a2; // foo class <int,int>
foo<float> a3; // foo class <float,int>
foo<double> b; // foo class <double,double>

Thank you,
Patrick
 
T

tom_usenet

Dear all,

I have a question about default template parameters.

I want to have a second template parameter which as a default parameter,
but depends on the first one (see below). Is something like that possible?

Default parameters are decided solely by the primary template -
specializations can't have defaults.
Some workaround?

Thank you,
Patrick


//Declaration (and definition)
template <typename T1=int,typename T2=T1> class foo{};

//Declaration and definition of partial specialization
//for T1=double.
int main()
{
foo<> a1; // foo class <int,int>
foo<int> a2; // foo class <int,int>
foo<float> a3; // foo class <float,int>

This will give foo<float, float>. If that isn't what you want (and you
want foo<float, int>), you'll have to say why, and why double should
be different.

Tom
 
P

Patrick Kowalzick

Dear Tom,

thanks for your help. I tried to strip the problem as much as I can and you
find the result below.

The aim is to get a function foo() which has different return types when
called with different template parameters. Sure you will say, this could be
critical from a semantic point of view, but in this case it is not, as the
return types have same meanings and behaviour (anyway they have to be
different, e.g bounded_vector<double,3> and bounded_vector<double,2> as
fixed size vectors which is close to my real problem).

Normally class_A and class_B are templated classes as well, what makes it
neccessary to use a partial specialized class to get a kind of "partial
specialized function". This is an explanation for the "huge" overhead below.

Anyway, I have a possibility with one return type which works fine (like in
the comment part below as a default template argument), but the other would
be nicer :).

Regards,
Patrick

P.S.: Is this an answer to the question why, or not? LOL

#include <iostream>

class class_A {};
class class_B {};

struct return_A
{
static void print() { std::cout << "Return Type return_A" << std::endl; }
};
struct return_B
{
static void print() { std::cout << "Return Type return_B" << std::endl; }
};


template < typename T , typename r_type > class foo_class;

template < typename r_type > class foo_class < class_A , r_type >
{
public:
typedef r_type return_type;
static return_type foo() {
std::cout << "Specialization < class_A >, ";
return_type::print();
return return_type();
}
};

template < typename r_type > class foo_class < class_B , r_type >
{
public:
typedef r_type return_type;
static return_type foo() {
std::cout << "Specialization < class_B >, ";
return_type::print();
return return_type();
}
};




template < typename T , typename return_type>
return_type foo()
{
return foo_class< T , return_type>::foo();
}

int main()
{

// These calls work quite fine, but I want to have an easier interface
foo< class_A , return_A > ();
foo< class_A , return_B > ();

foo< class_B , return_A > ();
foo< class_B , return_B > ();

// Simpilfied calls
// foo< class_A > (); // shall result in foo< class_A , return_A > ();
as default
// foo< class_B > (); // shall result in foo< class_B , return_B > ();
as default

// changing
// template < typename T , typename r_type > class foo_class;
// to
// template < typename T , typename r_type = return_A> class foo_class;
// does not help at all :-(

return 0;
}
 
T

tom_usenet

Dear Tom,

thanks for your help. I tried to strip the problem as much as I can and you
find the result below.

The aim is to get a function foo() which has different return types when
called with different template parameters. Sure you will say, this could be
critical from a semantic point of view, but in this case it is not, as the
return types have same meanings and behaviour (anyway they have to be
different, e.g bounded_vector<double,3> and bounded_vector<double,2> as
fixed size vectors which is close to my real problem).

Normally class_A and class_B are templated classes as well, what makes it
neccessary to use a partial specialized class to get a kind of "partial
specialized function". This is an explanation for the "huge" overhead below.

Ok, I think. It might be clearer if you used the real class names
below.
Anyway, I have a possibility with one return type which works fine (like in
the comment part below as a default template argument), but the other would
be nicer :).

Regards,
Patrick

P.S.: Is this an answer to the question why, or not? LOL

Just about, I think.

#include <iostream>

class class_A {};
class class_B {};

struct return_A
{
static void print() { std::cout << "Return Type return_A" << std::endl; }
};
struct return_B
{
static void print() { std::cout << "Return Type return_B" << std::endl; }
};

You've got nothing tying class_A to its default return, return_A. One
possibility is:

class class_A
{
public:
typedef return_A default_return_type;
};

template < typename T , typename r_type > class foo_class;

template < typename r_type > class foo_class < class_A , r_type >
{
public:
typedef r_type return_type;
static return_type foo() {
std::cout << "Specialization < class_A >, ";
return_type::print();
return return_type();
}
};

template < typename r_type > class foo_class < class_B , r_type >
{
public:
typedef r_type return_type;
static return_type foo() {
std::cout << "Specialization < class_B >, ";
return_type::print();
return return_type();
}
};

template < typename T , typename return_type>
return_type foo()
{
return foo_class< T , return_type>::foo();
}

int main()
{

// These calls work quite fine, but I want to have an easier interface
foo< class_A , return_A > ();
foo< class_A , return_B > ();

foo< class_B , return_A > ();
foo< class_B , return_B > ();

// Simpilfied calls
// foo< class_A > (); // shall result in foo< class_A , return_A > ();
as default
// foo< class_B > (); // shall result in foo< class_B , return_B > ();
as default

// changing
// template < typename T , typename r_type > class foo_class;
// to
// template < typename T , typename r_type = return_A> class foo_class;
// does not help at all :-(

return 0;
}

Ok, you want the syntax

foo<class_A>();

Since you can't have default template arguments for functions, you
need an overload of foo. You also need to tie class_A to return_A in
some way. If you can put the typedef suggested above into class_A,
then this works:

template <class T>
typename T::default_return_type foo()
{
return foo_class<T, typename T::default_return_type>::foo();
}

If you can't modify class_A, class_B, etc., you might add the
information to your specializations of foo_class. e.g.

template<typename T>
class foo_class;

template<>
class foo_class<class_A>
{
public:
typedef return_A default_return_type;
template <class return_type>
static return_type foo() {
std::cout << "Specialization<class_A>, ";
return_type::print();
return return_type();
}
};

template<>
class foo_class<class_B>
{
public:
typedef return_B default_return_type;
template <class return_type>
static return_type foo() {
std::cout << "Specialization<class_B>, ";
return_type::print();
return return_type();
}
};

template<typename T, typename return_type>
return_type foo()
{
return foo_class<T>::template foo<return_type>();
}

template<typename T>
typename foo_class<T>::default_return_type foo()
{
return foo_class<T>::template
foo<typename foo_class<T>::default_return_type>();
}


If you need to leave foo_class as it is, the final possibility is to
add separate traits binding a class to its default return:

template<class T>
struct foo_defaut_return;

template<>
struct foo_defaut_return<class_A>
{
typedef return_A type;
};

template<>
struct foo_defaut_return<class_B>
{
typedef return_B type;
};

And now foo looks like this:

template<typename T, typename return_type>
return_type foo()
{
return foo_class<T, return_type>::foo();
}

template<typename T>
typename foo_defaut_return<T>::type foo()
{
return foo_class<T, typename foo_defaut_return<T>::type>::foo();
}

Or similar. Anyway, I hope that gives you some ideas.

Tom
 
P

Patrick Kowalzick

Dear Tom,

I will try your proposals and hope to get it running.

Anyway your explanations solved two other problems I had ;-)

Thanks a lot.
Patrick
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,141
Messages
2,570,818
Members
47,367
Latest member
mahdiharooniir

Latest Threads

Top