C++: Partial template specialization - c++

I'm not getting the partial template specialization.
My class looks like this:
template<typename tVector, int A>
class DaubechiesWavelet : public AbstractWavelet<tVector> { // line 14
public:
static inline const tVector waveletCoeff() {
tVector result( 2*A );
tVector sc = scalingCoeff();
for(int i = 0; i < 2*A; ++i) {
result(i) = pow(-1, i) * sc(2*A - 1 - i);
}
return result;
}
static inline const tVector& scalingCoeff();
};
template<typename tVector>
inline const tVector& DaubechiesWavelet<tVector, 1>::scalingCoeff() { // line 30
return tVector({ 1, 1 });
}
The error gcc outputs is:
line 30: error: invalid use of incomplete type ‘class numerics::wavelets::DaubechiesWavelet<tVector, 1>’
line 14: error: declaration of ‘class numerics::wavelets::DaubechiesWavelet<tVector, 1>’
I've tried several solutions, but none worked.
Anybody has a hint for me?

template<typename tVector>
inline const tVector& DaubechiesWavelet<tVector, 1>::scalingCoeff() { // line 30
return tVector({ 1, 1 });
}
That's a definition of a member of a partial specialization that would be defined as follows
template<typename tVector>
class DaubechiesWavelet<tVector, 1> {
/* ... */
const tVector& scalingCoeff();
/* ... */
};
It's not a specialization of the member "scalingCoeff" of the primary template "DaubechiesWavelet". Such a specialization is required to pass the value of all arguments, which your specialization does not do. To do what you want, you can use overloading though
template<typename tVector, int A>
class DaubechiesWavelet : public AbstractWavelet<tVector> { // line 14
template<typename T, int I> struct Params { };
public:
static inline const tVector waveletCoeff() {
tVector result( 2*A );
tVector sc = scalingCoeff();
for(int i = 0; i < 2*A; ++i) {
result(i) = pow(-1, i) * sc(2*A - 1 - i);
}
return result;
}
static inline const tVector& scalingCoeff() {
return scalingCoeffImpl(Params<tVector, A>());
}
private:
template<typename tVector1, int A1>
static inline const tVector& scalingCoeffImpl(Params<tVector1, A1>) {
/* generic impl ... */
}
template<typename tVector1>
static inline const tVector& scalingCoeffImpl(Params<tVector1, 1>) {
return tVector({ 1, 1 });
}
};
Notice that the initialization syntax you use will only work in C++0x.

I don't see the class specialized. You must specialize the class, and inside it, the method.

Related

partial specialize a template function with a partial specilized template class [duplicate]

This question already has answers here:
Why function template cannot be partially specialized?
(4 answers)
C++ function template partial specialization?
(7 answers)
Closed 25 days ago.
I have a template function and a partial specialized version of it like this:
template<typename _T>
int values_in_range(const _T &beg, const _T &end) {
throw std::runtime_error("unsupoorted data type");
}
template<>
int values_in_range<int>(const int &beg, const int &end) {
return end - beg;
}
These code works good and then I want to extend the capabilities of the function to a template class that have two template parameters like this:
template<typename _Ty, size_t _Dims>
class vec {
// ...
};
How to partial specialize the function values_in_range for class vec with keeping the parameter _Dims unspecialized?
I try following code but encount error:
template<size_t _Dims>
int values_in_range<vec<int, _Dims>>(const vec<int, _Dims> &beg,
const vec<int, _Dims> &end) { // <-- compiling error
int ret = 0;
for (int i = 0; i < _Dims; ++i) {
//some computing here
}
return ret;
}
The error message:
error: non-class, non-variable partial specialization ‘values_in_range<vec<int, _Dims> >’ is not allowed
[build] 349 | int values_in_range<vec<int, _Dims>>(const vec<int, _Dims> &beg,
[build] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There is no partial specialization of function templates. Your first snippet of code is no partial specialization. You can partially specialize class templates. A function template can usually be refactored to a class template with operator().
template<typename _T>
struct values_in_range {
int operator()(const _T &beg, const _T &end) const {
throw 42;
}
};
template<>
struct values_in_range<int> {
int operator()(const int &beg, const int &end) const {
return end - beg;
}
};
template<typename _Ty, unsigned _Dims>
class vec {};
template<unsigned _Dims>
struct values_in_range<vec<int,_Dims>> {
int operator()(const vec<int, _Dims> &beg, const vec<int, _Dims> &end) const {
int ret = 0;
for (int i = 0; i < _Dims; ++i) {
//some computing here
}
return ret;
}
};

Undefined function error when calling a static constexpr function with CRTP

I'm trying to understand the reason for the compilation error with my CRTP implementation in this example:
template<class T>
struct Interface
{
static constexpr int func();
static constexpr int func2();
};
template<class T>
struct Default : public Interface<T>
{
constexpr static int impl_func()
{
return 0;
}
constexpr static int impl_func2()
{
return Default<T>::func() + 2; <----------- (A)
}
};
struct Derived : public Default<Derived>
{
static constexpr int impl_func2()
{
// NOTE: Using impl_func instead of func here compiles
return func() + 4; <-------------- (B)
}
};
struct Derived2 : public Default<Derived2>
{
};
template <typename T> constexpr int Interface<T>::func()
{
return T::impl_func();
}
template <typename T> constexpr int Interface<T>::func2()
{
return T::impl_func2();
}
int main()
{
constexpr int ret = Derived::func2();
static_assert(ret == 4);
constexpr int ret2 = Derived2::func2();
static_assert(ret2 == 2);
}
Specifically why is (A) ok while (B) gives me this error:
test3.cpp:45:19: error: constexpr variable 'ret' must be initialized by a constant expression
constexpr int ret = Derived::func2();
^ ~~~~~~~~~~~~~~~~
test3.cpp:29:16: note: undefined function 'func' cannot be used in a constant expression
return func() + 4;
Replacing (B) with return impl_func() + 4 compiles successfully. But neither Derived::func() nor Default<Derived>::func() work. If (B) needs to be impl_func() then is there something different about the fact that (A) is in a templated class that allows it to compile successfully?
With constexpr function, definition should be available when used...
reordering function definition solve the issue:
template<class T>
struct Interface
{
static constexpr int func();
static constexpr int func2();
};
template <typename T> constexpr int Interface<T>::func()
{
return T::impl_func();
}
template <typename T> constexpr int Interface<T>::func2()
{
return T::impl_func2();
}
// Remaining code.
Demo

Convenient constexpr-function

I can write a constexpr function that performs type deduction but does not use the object passed to it:
template <int N>
struct Foo
{
static const int value = N;
};
template <typename T>
constexpr int get_value(T const &)
{
return T::value;
}
void huey()
{
Foo<3> three;
static_assert(get_value(three) == 3, ":(");
}
However, if the argument to get_value is the result of some other operation, this approach fails:
template <int N>
Foo<N + 1> increase(Foo<N> const &)
{
return {};
}
void dewey()
{
Foo<6> six;
static_assert(get_value(increase(six)) == 7, ":(");
}
The compiler (rightfully) complains that increase(six) is not a constant expression. I can fix this like this:
template <typename T>
constexpr int get_value2()
{
return T::value;
}
void louie()
{
Foo<4> four;
static_assert(get_value2<decltype(increase(four))>() == 5, ":(");
}
but I do not like the extra decltype-gymnastics. I could introduce a macro:
#define GET_VALUE(x) get_value2<decltype(x)>()
but I would like to avoid macros, if possible. Is there any way to allow the convenient syntax get_value(some_function(some_object)) without macros?
increase() needs to be constexpr too
template <int N>
struct Foo
{
static const int value = N;
};
template <typename T>
constexpr int get_value(T const &)
{
return T::value;
}
void huey()
{
Foo<3> three;
static_assert(get_value(three) == 3, ":(");
}
template <int N>
constexpr Foo<N + 1> increase(Foo<N> const &)
{
return {};
}
void dewey()
{
Foo<6> six;
static_assert(get_value(increase(six)) == 7, ":(");
}

C++ template member function already defined with same type

I have this simple code below, a template with 2 type parameters. If I declare my class with the same type (like BidirectionalMap<int,int>), I receive an error:
int BidirectionalMap<T,S>::operator [](T) const' : member function already defined or declared
Here's my template code:
template <class T, class S>
class BidirectionalMap{
int count(T t){
return 1;
}
int count(S s){
return 1;
}
};
The error you got is normal, because after substitution you have
template <>
class BidirectionalMap<int, int>
{
int count(int t){ return 1; }
int count(int s){ return 1; } // Duplicated method
};
To solve that, you may provide partial specialization:
template <class T>
class BidirectionalMap<T, T>
{
int count(T t) { return 1; }
};
In C++20, you might use requires to "discard" methods:
template <class T, class S>
class BidirectionalMap
{
int count(T t) requires(!std::is_same<T, S>::value) { /*..*/ }
int count(S s) requires(!std::is_same<T, S>::value) { /*..*/ }
int count(T t) requires( std::is_same<T, S>::value) { /*..*/ }
};

division by zero with a template argument

I have a template
template<size_t N>
class Foo {
int bar(int a) {
if (N == 0)
return 0;
return a / N;
}
}
when I instantiate this with 0
Foo<0> bar;
gcc is too smart and reports division by zero at compile time
I tried
class Foo<size_t N> {
template<size_t M>
int bar(int a) {
return a / N;
}
template<>
int bar<0>(int a) {
return 0;
}
};
but this gives me error:
error: explicit specialization in non-namespace scope 'class Foo'
error: template-id 'bar<0>' in declaration of primary template
any ideas how I could solve/workaround this?
You can always rethink the formula:
template<size_t N>
class Foo {
bool bar() {
return N == 0 || (N >=5 && N < 10);
}
}
You can create a template specialization for Foo<0>.
template <>
class Foo<0> {
public:
bool bar () { return true; }
};
If you only want to address the issue with bar alone, and not touch any other part of Foo, you can create a companion method to avoid the issue:
template <size_t N>
class Foo
{
bool bar(int n) {
if (n == 0) return true;
return 5 / n == 1;
}
public:
bool bar() { return bar(N); }
};
Or pull the implementation of that method out into its own class, and specialize that:
template <size_t N>
class Bar
{
public:
bool operator() const { return 5 / N == 1; }
};
template <>
class Bar<0>
{
public:
bool operator() const { return true; }
};
template <size_t N>
class Foo {
bool bar() { return Bar<N>()(); }
};
Alternatively, you can use Jarod42's suggestion, and specialize the method itself (answer reiterated here for completeness).
template <size_t N>
class Foo
{
public:
bool bar() { return 5 / N == 1; }
};
template <> inline bool Foo<0>::bar() { return true; }
You may specialize the method:
template <size_t N> class Foo
{
public:
bool bar()
{
return 5 / N == 1;
}
};
template <>
bool Foo<0>::bar() { return true; }
Live example
To avoid multiple definitions, you have to define the function only once, or use inline, so
// In header
template <>
inline bool Foo<0>::bar() { return true; }
or
// In header: declaration of the specialization
template <>
bool Foo<0>::bar();
// in cpp: definition of the specialization.
template <>
bool Foo<0>::bar() { return true; }