Help: template function specialisation must accept scalar types only

  • Thread starter Martin MacRobert
  • Start date
M

Martin MacRobert

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
 
M

Marco Manfredini

Martin said:
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 said:
::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
 
T

Terje Slettebø

Martin MacRobert said:
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
 

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,997
Messages
2,570,240
Members
46,830
Latest member
HeleneMull

Latest Threads

Top