S
Stephen Waits
Occasionally we want to perform a Sqrt where we don't need accuracy
and/or we have a good initial guess - a situation where an N-step Sqrt
series may be more optimal than a full on Sqrt(). For example:
template <unsigned int iterations>
T SqrtApprox(const T x, const T guess)
{
return SqrtApprox<iterations-1>( x, T(0.5f) * (guess + (x/guess)) );
}
template <>
T SqrtApprox<0>(const T x, const T guess)
{
return guess;
}
The problems came when I attempted to get this little template
metaprogram into our main Math<T> class which looks something like
this:
template <typename T>
class Math
{
public:
static T Sqrt(T x);
static T Sin(T x);
static T ASin(T x);
... // SqrtApprox should be in here
};
So, I've coded up a few simple examples describing the process I've
gone through in trying to get this to work...
This working example shows basically what I want to do - only in a
global scope.
template <unsigned int I>
float Iterative(float x)
{
return x + Iterative<I-1>(x);
}
template <>
float Iterative<0>(float x)
{
// specialize 0th iteration to stop template recursion
return 0.0f;
}
However, when I decide to put this into a class and template out
"float" (similar to the Math<T> class above) I run into problems with
the language; for example:
[Begin BROKEN example
template <class T>
class SomeClass
{
public:
template <unsigned int I>
static T Iterative(T x);
};
template <class T>
template <unsigned int I> // not allowed!
T SomeClass<T>::Iterative<I>(T x)
{
}
--end BROKEN example]
Because this is a static member I cannot specialize it (because I
believe this is a function template, of which specialization is NOT
allowed by C++). Correct me if I'm wrong.
So, my next step is attempting to put this in a nested functor:
[Begin BROKEN example
template <class T>
class SomeClass
{
public:
template <unsigned int I>
class Iterative
{
public:
static T IterativeImpl(T x);
};
};
template <class T>
template <unsigned int I>
T SomeClass<T>::Iterative<I>::IterativeImpl(T x)
{
}
template <class T>
template <> // not allowed!
T SomeClass<T>::Iterative<0>::IterativeImpl(T x)
{
}
--end BROKEN example]
And, of course, as you experts know already, specialization of this
nested class is not allowed because the enclosing class template is
not specialized. Again, correct me if I'm wrong here.
What do you suggest I do to work around these issues?
Thanks,
Steve
and/or we have a good initial guess - a situation where an N-step Sqrt
series may be more optimal than a full on Sqrt(). For example:
template <unsigned int iterations>
T SqrtApprox(const T x, const T guess)
{
return SqrtApprox<iterations-1>( x, T(0.5f) * (guess + (x/guess)) );
}
template <>
T SqrtApprox<0>(const T x, const T guess)
{
return guess;
}
The problems came when I attempted to get this little template
metaprogram into our main Math<T> class which looks something like
this:
template <typename T>
class Math
{
public:
static T Sqrt(T x);
static T Sin(T x);
static T ASin(T x);
... // SqrtApprox should be in here
};
So, I've coded up a few simple examples describing the process I've
gone through in trying to get this to work...
This working example shows basically what I want to do - only in a
global scope.
template <unsigned int I>
float Iterative(float x)
{
return x + Iterative<I-1>(x);
}
template <>
float Iterative<0>(float x)
{
// specialize 0th iteration to stop template recursion
return 0.0f;
}
However, when I decide to put this into a class and template out
"float" (similar to the Math<T> class above) I run into problems with
the language; for example:
[Begin BROKEN example
template <class T>
class SomeClass
{
public:
template <unsigned int I>
static T Iterative(T x);
};
template <class T>
template <unsigned int I> // not allowed!
T SomeClass<T>::Iterative<I>(T x)
{
}
--end BROKEN example]
Because this is a static member I cannot specialize it (because I
believe this is a function template, of which specialization is NOT
allowed by C++). Correct me if I'm wrong.
So, my next step is attempting to put this in a nested functor:
[Begin BROKEN example
template <class T>
class SomeClass
{
public:
template <unsigned int I>
class Iterative
{
public:
static T IterativeImpl(T x);
};
};
template <class T>
template <unsigned int I>
T SomeClass<T>::Iterative<I>::IterativeImpl(T x)
{
}
template <class T>
template <> // not allowed!
T SomeClass<T>::Iterative<0>::IterativeImpl(T x)
{
}
--end BROKEN example]
And, of course, as you experts know already, specialization of this
nested class is not allowed because the enclosing class template is
not specialized. Again, correct me if I'm wrong here.
What do you suggest I do to work around these issues?
Thanks,
Steve