By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,928 Members | 1,210 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,928 IT Pros & Developers. It's quick & easy.

Help: template function specialisation must accept scalar types only

P: n/a
Hi,
I'm trying to make a specialisation of a template function, so that
the second parameter accepts scalar types only (int,double,float
etc.).

How can I do this without writing an explicit specialisation for all
scalar types? This is because of the large number of functions to
overload.

For example:
// where BinaryExpr is declared
class BinaryExpr:
public Expression< BinaryExpr<Expr1, Expr2, Op> >
{...};

//+ operator General case
template <typename Expr1, typename Expr2>
BinaryExpr< Expr1, Expr2, std::plus >
operator +(const Expression<Expr1>& expr1, const Expression<Expr2>&
expr2)
{...}

// I want to AVOID writing a specialisation for each scalar type as
shown below:
template <typename Expr1>
BinaryExpr< Expr1, int, std::plus >
operator +(const Expression<Expr1>& expr1, int expr2)
{...}

I have a "literal" class that can take a scalar in the constructor.
"Literal" is also derived from "Expression" in a "curious" fashion,
however if I specialise the operator "+" for "Literal", the overload
is ambiguous.

I tried creating a "Scalar" template not derived from Expression, that
has no implementation for non-scalars and fully implemented for each
scalar type. The compiler still could not deduce the appropriate type
for the scalar.

Any help much appreciated.
Thanks,
Martin

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #1
Share this Question
Share on Google+
2 Replies


P: n/a
Martin MacRobert wrote:
Hi,
I'm trying to make a specialisation of a template function, so that
the second parameter accepts scalar types only (int,double,float
etc.). [snipped]

The canonical solution would be ::boost::enable_if.

Here is how it works:

/* enable_if is a kind of compile time conditional. */
template<bool b, class T>
struct enable_if_c
{
};

template<class T>
struct enable_if_c<true>
{
typedef T type;
};

/*
The difference between these both is, that enable_if<true,int> contains
a typedef 'type' which is 'int', while enable_if<false,int> doesn't
contain anything.
*/

/* now enumerate the scalar types you want: */

template<class T>
struct is_scalar_type { static const bool value=false; };
template<>
is_scalar_type<int> { static const bool value=true; };
template<>
is_scalar_type<double> { static const bool value=true; };
// etc..

/*
so
enable_if_c< is_scalar_type<int>::value, int >
contains the typedef type
enable_if_c< is_scalar_type<void*>::value, void* >
doesn't contain a typedef
*/

/*
Now you can declare an operator that accepts scalars as T only:
*/

template<class S,class T>
typename enable_if_c<
is_scalar_type<T>::value,
BinaryExpr<S,T,std::plus>::type operator + (const BinExpr<S>&s, T t);


You see what happens? if T is a "scalar_type" then the return type is
declared to be a BinaryExpr<..>, but otherwise there is no typedef
named 'type' there and, that's heres the twist: the compiler ignores
this specific template because he finds that it doesn't match the
requested application.

Regards
Marco
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #2

P: n/a
"Martin MacRobert" <mj*********@yahoo.com> wrote in message
news:27**************************@posting.google.c om...
Hi,
I'm trying to make a specialisation of a template function, so that
the second parameter accepts scalar types only (int,double,float
etc.).

How can I do this without writing an explicit specialisation for all
scalar types? This is because of the large number of functions to
overload.


You might want to check out Boost's enable_if
(http://www.boost.org/libs/utility/enable_if.html). An example:

#include <iostream>
#include <boost/type_traits/is_scalar.hpp>
#include <boost/utility/enable_if.hpp>

using namespace boost;

template<class T>
typename enable_if<is_scalar<T> >::type
f(T)
{
std::cout << "f(scalar)\n";
}

template<class T>
typename disable_if<is_scalar<T> >::type
f(T)
{
std::cout << "f(non-scalar)\n";
}

class test {};

int main()
{
f(1);
f(test());
}

Output:

f(scalar)
f(non-scalar)

Regards,

Terje

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.