Re: Function Template Specialization
In article <op.tl0g7bl0s1fyqh@mmgs-pc>, Markus Grueneis <mmg@gmx.at>
wrote:
Hi,
I recently came across some not so much but a bit surprising behaviour
when using a function template and some specializations. The code snippet
below is a bit verbose, maybe I'm missing something obvious.
I do have a template function get_value(), which returns a selected value
from an aggregate.
The template parameter is used to generalize of different types of such an
aggregate.
Then I do have a template function is_valid(), which returns a boolean
flag, depending on the aggregate content, and the set of the parameter.
So it has two template parameters (ValueSet, AggregateType).
//---------------------------------------------------------------------
//---------------------------------------------------------------------
#include <iostream>
typedef enum { id_1, id_2, id_3 } index_t;
struct FooSet {}; struct BarSet {};
typedef std::pair<int, bool> baz_t; // (value, currently-valid-flag)
//---------------------------------------------------------------------
template<class ParameterSet, class Aggregate>
bool is_valid(const Aggregate& dat) { return false; }
template<>
bool is_valid<FooSet, class Aggregate> (const Aggregate& dat) {
return true;
}
template<>
bool is_valid<BarSet, class Aggregate> (const Aggregate& dat) {
return true;
}
//---------------------------------------------------------------------
template<class Aggregate>
baz_t get_value(const Aggregate& dat, index_t id) {
switch(id) {
case id_1: return baz_t(dat.member_1, is_valid<FooSet>(dat));
case id_2: return baz_t(dat.member_2, is_valid<BarSet>(dat));
case id_3: return baz_t(dat.member_3, is_valid<BarSet>(dat));
default: throw std::exception();
}
}
//---------------------------------------------------------------------
struct some_aggregate {
int member_1; // element of set foo
int member_2; // element of set bar
int member_3; // element of set bar
};
//---------------------------------------------------------------------
int main() {
using namespace std;
some_aggregate blub = { 1, 2 };
baz_t one(get_value(blub, id_1));
baz_t two(get_value(blub, id_2));
cout << "id_1: " << one.first << " | " << one.second << endl;
cout << "id_2: " << two.first << " | " << two.second << endl;
return 0;
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------
The program prints:
id_1: 1 | 0
id_2: 2 | 0
But I would like it to print
id_1: 1 | 1
id_2: 2 | 1
I have solved my specific task just using class and member templates quite
easily, but I would like to know if there would have been just some
syntactic sugar (I tried different syntaxes, but without understanding
this leads to nothing). I think I've read about the this issue, but the
C++ FAQ Template section is silent about it, and I can't remember any
keywords. Any reading suggestions would be very nice.
overload the functions something like.
template <class T>
struct id{typedef T type;};
template <class A,class U>
rv foo_do(const A &a,T )
{
typedef typename T::type param_type;
// default operation
}
template <class A>
rv foo_do(const A &,id<FooSet>)
{
// handle fooset;
}
template <class A>
rv foo_do(const A &a,id<BarSet>)
{
// handle BarSet
}
template <class T,class A>
rv foo(const A &a)
{
return foo_do(a,id<T>());
}
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]