Function template specialization

S

sheffmail

I have the following code:

template <class T>
struct MyS
{
};

template<class T>
inline const T& function(const std::locale& loc)
{
std::cout << "generic" << std::endl;
}

template <class CharType, class Traits, class Allocator>
inline const MyS said:
(const std::locale& loc)
{
std::cout << "specialized" << std::endl;
}

int main(int argc, char* argv[])
{
function< MyS<std::string> >(std::locale()); //Should print
"specialized"
function< MyS<std::wstring> >(std::locale()); //Should print
"specialized"
function< MyS<int> >(std::locale()); //Should print "generic"

return 0;
}

Which doesn't compile, I believe it's because you can't partially
specialize function templates. But I really need to
get the desired behavior(Note the "Should print"s in comments), how
can this be done ?
 
S

sheffmail

I have the following code:
template <class T>
struct MyS
{
};
template<class T>
inline const T& function(const std::locale& loc)
{
std::cout << "generic" << std::endl;
}
template <class CharType, class Traits, class Allocator>

{
std::cout << "specialized" << std::endl;
}
int main(int argc, char* argv[])
{
function< MyS<std::string> >(std::locale()); //Should print
"specialized"
function< MyS<std::wstring> >(std::locale()); //Should print
"specialized"
function< MyS<int> >(std::locale()); //Should print "generic"
return 0;
}
Which doesn't compile, I believe it's because you can't partially
specialize function templates.
Correct.

But I really need to
get the desired behavior(Note the "Should print"s in comments), how
can this be done ?

You can invent your own traits class and specialise that (or *on* that).
Full specialisations of function templates *are* allowed.

Oh, forgot to mention that I need to get this behavior without
changing the signature of generic function:

template<class T>
inline const T& function(const std::locale& loc)

Is it possible ?
BTW, what's the role of 'MyS' template here? It seems superfluous.

Yes, in this simple example it's insignificant, though it matters in
context from which this code was taken.
 
D

Daniel Pitts

Victor said:
(e-mail address removed) wrote:
I have the following code:
template <class T>
struct MyS
{
};
template<class T>
inline const T& function(const std::locale& loc)
{
std::cout << "generic" << std::endl;
}
template <class CharType, class Traits, class Allocator>
inline const MyS< std::basic_string<CharType, Traits, Allocator> >&
function< MyS< std::basic_string<CharType, Traits, Allocator> >
(const std::locale& loc)
{
std::cout << "specialized" << std::endl;
}
int main(int argc, char* argv[])
{
function< MyS<std::string> >(std::locale()); //Should print
"specialized"
function< MyS<std::wstring> >(std::locale()); //Should print
"specialized"
function< MyS<int> >(std::locale()); //Should print "generic"
return 0;
}
Which doesn't compile, I believe it's because you can't partially
specialize function templates.
Correct.

But I really need to

get the desired behavior(Note the "Should print"s in comments), how
can this be done ?
You can invent your own traits class and specialise that (or *on* that).
Full specialisations of function templates *are* allowed.

Oh, forgot to mention that I need to get this behavior without
changing the signature of generic function:

template<class T>
inline const T& function(const std::locale& loc)

Is it possible ?

So, you have a function template that you want to behave differently if
you give it some special *set of* Ts, right. And that set is unbounded,
right? If it is, the solution is to wrap those in a class template and
specialise that:

template<class T> struct Caller {
static T& call(const std::locale& loc) {
return function<T>(loc);
}
};

template<class T, class U> struct Caller<MyS<T,U> > {
static MyS<T,U>& call(const std::locale& loc) {
return function<MyS<T,U> >(loc);
}
};

Of course in that case you need to refactor the code that calls the
functions from

function<blah>(loc);

to

Caller<blah>::function(loc);

V
Or replace function<blah> implementation to forward to
Caller<blah>::function until you can refactor.
 
S

sheffmail

Victor said:
(e-mail address removed) wrote:
I have the following code:
template <class T>
struct MyS
{
};
template<class T>
inline const T& function(const std::locale& loc)
{
std::cout << "generic" << std::endl;
}
template <class CharType, class Traits, class Allocator>
inline const MyS< std::basic_string<CharType, Traits, Allocator> >&
function< MyS< std::basic_string<CharType, Traits, Allocator> >
(const std::locale& loc)
{
std::cout << "specialized" << std::endl;
}
int main(int argc, char* argv[])
{
function< MyS<std::string> >(std::locale()); //Should print
"specialized"
function< MyS<std::wstring> >(std::locale()); //Should print
"specialized"
function< MyS<int> >(std::locale()); //Should print "generic"
return 0;
}
Which doesn't compile, I believe it's because you can't partially
specialize function templates.
Correct.
But I really need to
get the desired behavior(Note the "Should print"s in comments), how
can this be done ?
You can invent your own traits class and specialise that (or *on* that).
Full specialisations of function templates *are* allowed.
Oh, forgot to mention that I need to get this behavior without
changing the signature of generic function:
template<class T>
inline const T& function(const std::locale& loc)
Is it possible ?
So, you have a function template that you want to behave differently if
you give it some special *set of* Ts, right. And that set is unbounded,
right? If it is, the solution is to wrap those in a class template and
specialise that:
template<class T> struct Caller {
static T& call(const std::locale& loc) {
return function<T>(loc);
}
};
template<class T, class U> struct Caller<MyS<T,U> > {
static MyS<T,U>& call(const std::locale& loc) {
return function<MyS<T,U> >(loc);
}
};
Of course in that case you need to refactor the code that calls the
functions from



V

Or replace function<blah> implementation to forward to
Caller<blah>::function until you can refactor.

That's the problem, I can't modify declaration nor implementation of
"generic" function, because it's actually std::use_facet from STL and
I need to specialize it for my type, which is std::ctype< MyS<...> >
 
J

jason.cipriani

That's the problem, I can't modify declaration nor implementation of
"generic" function, because it's actually std::use_facet from STL and
I need to specialize it for my type, which is std::ctype< MyS<...> >

I don't know if this fit's all your requirements but here is the
closest I could get:

=== BEGIN CODE ===

template<class T>
inline const T& function(const std::locale& loc)
{
std::cout << "generic" << std::endl;

}

// this is your implementation of the specialized function; you only
have to
// do it once, at least that's a plus.
template <class T>
inline const MyS<T> & function_mys (const std::locale &) {
std::cout << "specialized" << std::endl;
}

// but you still have to at least have these one-ish liners for each
string
// type; you lose some genericness there.
template <>
inline const MyS<std::string> & function<MyS<std::string> >
(const std::locale &loc) {
return function_mys<std::string>(loc);
}

template <>
inline const MyS<std::wstring> & function<MyS<std::wstring> >
(const std::locale &loc) {
return function_mys<std::wstring>(loc);
}

=== END CODE ===

The idea there is that you explicitly specialize for every
std::basic_string type you'll be using; but you pass everything off to
function_mys so you still only have to maintain one copy of the
specialized code. Still that means you lose the flexibility of passing
*any* basic_string<A,B,C> since you have to explicitly specialize each
of those short functions.

Jason
 
S

sheffmail

I don't know if this fit's all your requirements but here is the
closest I could get:

=== BEGIN CODE ===

template<class T>
inline const T& function(const std::locale& loc)
{
std::cout << "generic" << std::endl;

}

// this is your implementation of the specialized function; you only
have to
// do it once, at least that's a plus.
template <class T>
inline const MyS<T> & function_mys (const std::locale &) {
std::cout << "specialized" << std::endl;

}

// but you still have to at least have these one-ish liners for each
string
// type; you lose some genericness there.
template <>
inline const MyS<std::string> & function<MyS<std::string> >
(const std::locale &loc) {
return function_mys<std::string>(loc);

}

template <>
inline const MyS<std::wstring> & function<MyS<std::wstring> >
(const std::locale &loc) {
return function_mys<std::wstring>(loc);

}

=== END CODE ===

The idea there is that you explicitly specialize for every
std::basic_string type you'll be using; but you pass everything off to
function_mys so you still only have to maintain one copy of the
specialized code. Still that means you lose the flexibility of passing
*any* basic_string<A,B,C> since you have to explicitly specialize each
of those short functions.

Jason

Though I lose flexibility, there's probably no better way to solve my
problem, I guess I use this idea.
Thanks a lot!
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,163
Latest member
Sasha15427
Top