I want to have general class Vector of any dimensions with template type
template <typename T, unsigned D>
class Vector {
public:
// constructors, methods and so on
protected:
T data[D];
};
and specializations for 2, 3 and 4 dimensions
template <typename T, unsigned D>
class Vector<T, 3> {
public:
T getX() const { return data[0]; }
// ...
};
this code, of course, doesn't work. How should I do it? If it is possible. Or, in any cases, I should use inheritance?
template <typename T>
class Vector3 : public Vector<T, 3> {
public:
T getX() const { return data[0]; }
};
gcc prints pretty straightforward error for your code:
error: template parameters not deducible in partial specialization: D
In order to set a partial specialization you should remove parameter D:
template <typename T> // <=== No *unsigned D* here
class Vector<T, 3> {
public:
// implementation here
};
and then implement the specialization.
Of course you can partially specialise your template class in any way. The only syntactic error you made is, that you should list the template parameters which are actually parameters (and not constants).
#include <iostream>
template <typename T, unsigned D>
class Vector {
public:
// constructors, methods and so on
protected:
T data[D];
};
template <typename T>
class Vector<T, 3> {
public:
// the same constructors (or not?)
T getX() const { return data[0]; }
T data[3];
};
int main() {
Vector<int, 3> arr;
arr.data[0]=42;
std::cout << arr.getX();
return 0;
}
Note that the specialization Vector<T,3> no longer lists D.
You can do whatever you want within the specialization. It can have a completely different body.
Related
The following code:
template <typename S, typename T>
struct foo {
void bar();
};
template <typename T>
void foo <int, T>::bar() {
}
gives me the error
invalid use of incomplete type 'struct foo<int, T>'
declaration of 'struct foo<int, T>'
(I'm using gcc.) Is my syntax for partial specialization wrong? Note that if I remove the second argument:
template <typename S>
struct foo {
void bar();
};
template <>
void foo <int>::bar() {
}
then it compiles correctly.
You can't partially specialize a function. If you wish to do so on a member function, you must partially specialize the entire template (yes, it's irritating). On a large templated class, to partially specialize a function, you would need a workaround. Perhaps a templated member struct (e.g. template <typename U = T> struct Nested) would work. Or else you can try deriving from another template that partially specializes (works if you use the this->member notation, otherwise you will encounter compiler errors).
Although coppro mentioned two solutions already and Anonymous explained the second one, it took me quite some time to understand the first one. Maybe the following code is helpful for someone stumbling across this site, which still ranks high in google, like me. The example (passing a vector/array/single element of numericalT as dataT and then accessing it via [] or directly) is of course somewhat contrived, but should illustrate how you actually can come very close to partially specializing a member function by wrapping it in a partially specialized class.
/* The following circumvents the impossible partial specialization of
a member function
actualClass<dataT,numericalT,1>::access
as well as the non-nonsensical full specialisation of the possibly
very big actualClass. */
//helper:
template <typename dataT, typename numericalT, unsigned int dataDim>
class specialised{
public:
numericalT& access(dataT& x, const unsigned int index){return x[index];}
};
//partial specialisation:
template <typename dataT, typename numericalT>
class specialised<dataT,numericalT,1>{
public:
numericalT& access(dataT& x, const unsigned int index){return x;}
};
//your actual class:
template <typename dataT, typename numericalT, unsigned int dataDim>
class actualClass{
private:
dataT x;
specialised<dataT,numericalT,dataDim> accessor;
public:
//... for(int i=0;i<dataDim;++i) ...accessor.access(x,i) ...
};
If you need to partially specialise a constructor, you might try something like:
template <class T, int N>
struct thingBase
{
//Data members and other stuff.
};
template <class T, int N> struct thing : thingBase<T, N> {};
template <class T> struct thing<T, 42> : thingBase<T, 42>
{
thing(T * param1, wchar_t * param2)
{
//Special construction if N equals 42.
}
};
Note: this was anonymised from something I'm working on. You can also use this when you have a template class with lots and lots of members and you just want to add a function.
If you're reading this question then you might like to be reminded that although you can't partially specialise methods you can add a non-templated overload, which will be called in preference to the templated function. i.e.
struct A
{
template<typename T>
bool foo(T arg) { return true; }
bool foo(int arg) { return false; }
void bar()
{
bool test = foo(7); // Returns false
}
};
In C++ 17, I use "if constexpr" to avoid specialize (and rewrite) my method. For example :
template <size_t TSize>
struct A
{
void recursiveMethod();
};
template <size_t TSize>
void A<TSize>::recursiveMethod()
{
if constexpr (TSize == 1)
{
//[...] imple without subA
}
else
{
A<TSize - 1> subA;
//[...] imple
}
}
That avoid to specialize A<1>::recursiveMethod().
You can also use this method for type like this example :
template <typename T>
struct A
{
void foo();
};
template <typename T>
void A<T>::foo()
{
if constexpr (std::is_arithmetic_v<T>)
{
std::cout << "arithmetic" << std::endl;
}
else
{
std::cout << "other" << std::endl;
}
}
int main()
{
A<char*> a;
a.foo();
A<int> b;
b.foo();
}
output :
other
arithmetic
I am thinking of creating template class wrapper that is supposed to inherit all of template parameter functionality and add something on top of it. For structs and classes this would be pretty simple
class foo{ void bar(){} };
template<class T>
class baz : public T { void zab(){} };
int main(){
baz<foo> a;
}
Now, my question is if there is any way to be able to keep operators for built-in integral types without tons of manual specializing template for those types to be able to do it like this:
int main(){
baz<int> a;
int b = a + 2;
}
Can it be done? If so, how? (I know it will be necessary to do it with some magic specialization. I am just asking if it is possible to do it with one partial specialization)
With SFINAE friend class, you may reduce the specializations with template:
template <class T, typename Enabler = void>
class baz : public T { void zab(){} };
// specialization for integral type
template <class T>
class baz<T, std::enable_if_t<std::is_integral<T>::value>>
{
friend auto operator + (T lhs, T rhs) { /*..*/}
operator T() const { return value; }
// ...
T value;
};
The following code:
template <typename S, typename T>
struct foo {
void bar();
};
template <typename T>
void foo <int, T>::bar() {
}
gives me the error
invalid use of incomplete type 'struct foo<int, T>'
declaration of 'struct foo<int, T>'
(I'm using gcc.) Is my syntax for partial specialization wrong? Note that if I remove the second argument:
template <typename S>
struct foo {
void bar();
};
template <>
void foo <int>::bar() {
}
then it compiles correctly.
You can't partially specialize a function. If you wish to do so on a member function, you must partially specialize the entire template (yes, it's irritating). On a large templated class, to partially specialize a function, you would need a workaround. Perhaps a templated member struct (e.g. template <typename U = T> struct Nested) would work. Or else you can try deriving from another template that partially specializes (works if you use the this->member notation, otherwise you will encounter compiler errors).
Although coppro mentioned two solutions already and Anonymous explained the second one, it took me quite some time to understand the first one. Maybe the following code is helpful for someone stumbling across this site, which still ranks high in google, like me. The example (passing a vector/array/single element of numericalT as dataT and then accessing it via [] or directly) is of course somewhat contrived, but should illustrate how you actually can come very close to partially specializing a member function by wrapping it in a partially specialized class.
/* The following circumvents the impossible partial specialization of
a member function
actualClass<dataT,numericalT,1>::access
as well as the non-nonsensical full specialisation of the possibly
very big actualClass. */
//helper:
template <typename dataT, typename numericalT, unsigned int dataDim>
class specialised{
public:
numericalT& access(dataT& x, const unsigned int index){return x[index];}
};
//partial specialisation:
template <typename dataT, typename numericalT>
class specialised<dataT,numericalT,1>{
public:
numericalT& access(dataT& x, const unsigned int index){return x;}
};
//your actual class:
template <typename dataT, typename numericalT, unsigned int dataDim>
class actualClass{
private:
dataT x;
specialised<dataT,numericalT,dataDim> accessor;
public:
//... for(int i=0;i<dataDim;++i) ...accessor.access(x,i) ...
};
If you need to partially specialise a constructor, you might try something like:
template <class T, int N>
struct thingBase
{
//Data members and other stuff.
};
template <class T, int N> struct thing : thingBase<T, N> {};
template <class T> struct thing<T, 42> : thingBase<T, 42>
{
thing(T * param1, wchar_t * param2)
{
//Special construction if N equals 42.
}
};
Note: this was anonymised from something I'm working on. You can also use this when you have a template class with lots and lots of members and you just want to add a function.
If you're reading this question then you might like to be reminded that although you can't partially specialise methods you can add a non-templated overload, which will be called in preference to the templated function. i.e.
struct A
{
template<typename T>
bool foo(T arg) { return true; }
bool foo(int arg) { return false; }
void bar()
{
bool test = foo(7); // Returns false
}
};
In C++ 17, I use "if constexpr" to avoid specialize (and rewrite) my method. For example :
template <size_t TSize>
struct A
{
void recursiveMethod();
};
template <size_t TSize>
void A<TSize>::recursiveMethod()
{
if constexpr (TSize == 1)
{
//[...] imple without subA
}
else
{
A<TSize - 1> subA;
//[...] imple
}
}
That avoid to specialize A<1>::recursiveMethod().
You can also use this method for type like this example :
template <typename T>
struct A
{
void foo();
};
template <typename T>
void A<T>::foo()
{
if constexpr (std::is_arithmetic_v<T>)
{
std::cout << "arithmetic" << std::endl;
}
else
{
std::cout << "other" << std::endl;
}
}
int main()
{
A<char*> a;
a.foo();
A<int> b;
b.foo();
}
output :
other
arithmetic
I already asked two questions related to what I'm trying to do (one resolved, one of which I will close soon). I know that C++ template instantiation does not allow any implicit conversions (see for example this comment), but I would like to simulate it.
Suppose I have the following skeleton code:
template <class T>
struct Base_A{
virtual void interface_func() const = 0;
};
template <class T>
struct Derived_A : public Base_A<T>{
typedef T value_type;
void interface_func() const{}
};
template <class T>
struct Base_B{
virtual void interface_func() = 0; // note: non-const
};
template <class T>
struct Derived_B : public Base_B<T>{
typedef T value_type;
void interface_func(){}
};
template <class BType>
struct Adapter : public Base_A<typename BType::value_type>{
BType &ref_B;
Adapter(BType &inst_B):ref_B(B_inst){}
void interface_func() const{} // does stuff with ref_B to simulate an A
};
template <class Should_Always_Be_Base_A>
void f(const Should_Always_Be_Base_A &arg){
// Only Base_A can be passed in by const ref
// Passing in a Base_B by const ref would not work.
}
Derived_A<int> A;
Derived_B<int> B;
f(A); // passes in A by const ref
f(B); // I want to pass in Adapter<Derived_B<int> >(B)
I want the template parameter for function f to always be a derived class of Base_A or an Adapter. The answer to restricting the type of arg can be done, but the implicit conversion to an Adapter cannot. Is there any way to do this? The net result is I want to be able to call f as f(A) or f(B), and in both cases I need to know the actual derived type of A or B within f (f cannot just see a reference to the base class).
Aside:
Presently, I just have f(A) working, and f(B) actually calls an overload which performs the Adapter construction, but I have other functions which take N arguments, each of which can be A or B, so I would need 2^N overloads.
For the curious, this is in application to the matrix library I'm working on. Base_A represents the base matrix type, and Base_B represents the base matrix-view type. For operations which will modify a matrix argument, I need to pass in the matrix by non-const reference or a modifiable matrix-view by const-ref. The adapter is just a trivial matrix-to-view adapter. So for example, I currently have a function like
Scale(const MatrixViewBase<T> &Mview, const T &scale_factor){
// does the actual work
}
Scale(MatrixBase<T> &M, const T &scale_factor){
Scale(Adapter<MatrixBase<T> >(M), scale_factor);
}
It's tedious and error prone to make 2^N copies of all these functions just to create the needed overloads to handle both views and non-views. As is, this is not good enough since I want Scale to be able to know the full derived type of Mview, not just the base class, because I will potentially generate instances of types dependent on Mview.
Edit 1: Changed all B types to have non-const interface functions. This was the original intent, so apologies for any confusion.
Edit 2: Have this working code, still requires 2^N overloads, but I can live with it unless someone suggests how to deal with that.
#include <iostream>
template <class T>
struct ReadableMatrix{
typedef T value_type;
};
template <class T>
struct WritableMatrix{
typedef T value_type;
};
template <class T>
struct WritableMatrixView{
typedef T value_type;
};
template <class T>
struct Matrix : public WritableMatrix<T>{
typedef T value_type;
typedef ReadableMatrix<T> readable_matrix;
typedef WritableMatrix<T> writable_matrix;
};
template <class T>
struct MatrixView : public WritableMatrixView<T>{
typedef T value_type;
typedef ReadableMatrix<T> readable_matrix; // not really used; needs an adapter before using
typedef WritableMatrixView<T> writable_matrix;
};
template <class T, class R>
struct IsReadableMatrix{
};
template <class T, class R>
struct IsReadableMatrix<ReadableMatrix<T>, R>{
typedef R type;
};
template <class T, class R>
struct IsWritableMatrix{
};
template <class T, class R>
struct IsWritableMatrix<WritableMatrix<T>, R>{
typedef R type;
};
template <class T, class R>
struct IsWritableMatrixView{
};
template <class T, class R>
struct IsWritableMatrixView<WritableMatrixView<T>, R>{
typedef R type;
};
template <class TA, class TB>
typename IsReadableMatrix<typename TA::readable_matrix,
typename IsWritableMatrixView<typename TB::writable_matrix,
void
>::type>::type
Copy(const TA &A, const TB &B){
std::cout << "Here" << std::endl;
}
template <class TA, class TB>
typename IsReadableMatrix<typename TA::readable_matrix,
typename IsWritableMatrix<typename TB::writable_matrix,
void
>::type>::type
Copy(const TA &A, TB &B){
std::cout << "Here2" << std::endl;
}
int main(){
Matrix<int> M, M2;
MatrixView<int> V, V2;
Copy(M, M2);
Copy(V, V2);
Copy(M, V);
Copy(V, M);
}
Do you need you base classes to be templates? Can you inject even "more base" nontemplate class?
If yes, you can do something like that:
struct Base_A{
virtual void interface_func() const = 0;
};
template <class T>
struct Derived_A : public Base_A{
typedef T value_type;
void interface_func() const{}
};
struct Base_B{
virtual void interface_func() const = 0;
};
template <class T>
struct Derived_B : public Base_B{
typedef T value_type;
void interface_func() const{}
};
struct Adapter
{
const Base_A* pA;
const Base_B* pB;
Adapter(const Base_B &inst_B) : pB(&inst_B), pA(0){}
Adapter(const Base_A &inst_A) : pA(&inst_A), pB(0){}
void interface_func() const
{
if( 0 != pA )
pA->interface_func();
else if( 0 != pB )
pB->interface_func();
}
};
void f(const Adapter &arg)
{
arg.interface_func(); // will call proper interface_func
}
int main()
{
Derived_A<int> A;
Derived_B<int> B;
f(A);
f(B);
}
Try the following:
template <template <typename> View, typename T>
struct Adapter
{
// Leave empty to cause errors if used, or you could
// provide a generic adapter for View<typename T::value_type>
}
// Partial specialization for a given base.
template <typename T>
struct Adapter<MatrixView, T> : MatrixView<typename T::value_type>
{
const T& t;
Adapter (const T& t)
: t(t)
{}
void some_virtual()
{
// Do stuff
}
}
template <template <typename> View, typename T>
const View<T>& adapt (const View<T>& v)
{
return v;
}
template <template <typename> View, typename T>
View<T> adapt (const T& t)
{
return Adapter<View, T>(t);
}
template <typename T, typename U>
foo(const MatrixViewBase<T> &Mview, const MatrixViewBase<U> &Mview2);
template <typename T, typename U>
foo (const T& t, const U& u)
{
return foo(adapt<MatrixViewBase>(t), adapt<MatrixViewBase>(u));
}
I put const in everywhere I could; you don't have to use it in every situation if it's not appropriate. You can use specializations of Adapter for a given T to further tailor the behavior.
Interestingly enough, this is the first time I've ever recommended template template parameters.
I have not looked into the details of a templated solution, but while you are at it, you can check the boost preprocessor library to help you in defining the 2^N variations of the template. This won't be nice on compile time, but it will be better than manually creating the variations.
I had to do this a while ago and the easiest (to maintain) solution I came up with was to have only one class (Matrix) that knows if it owns it's own data or is a view of someone else's data. E.g.,
Matrix A(n,m); //Creates a new matrix of size (n,m)
Matrix B=View(A); //Creates a matrix that's a view into A
Matrix C=View(pData,n,m); //Creates a matrix thats a view of data in a pointer that someone else owns
Foo(A);
Foo(B);
Foo(C);
It makes writing the Matrix class a little more difficult, but then later anyone who uses a Matrix, just uses it as a matrix, they don't need to care if it's a view or not.
Edited to add:
Why not just let BLAS manage the transpose for you? In the end, any of the BLAS functions are just going to want a pointer to a contiguous chunk of memory. So as long as your Matrix class knows how to get to that memory you're good. If the Matrix class has it's own isTransposed flag inside then you can do something like this:
Matrix A(n,m);
Matrix B=TransposedView(pData,m,n);
Matrix C=A*B;
Matrix& operator*(const Matrix& lhs, const Matrix& rhs)
{
Matrix result(lhs.Rows(),rhs.Cols()); //or did i get that backwards :)
char TransL=lhs.IsTransposed()?'T':'N';
char TransR=rhs.IsTransposed()?'T':'N';
_dgemm(TransL, TransR, ..., lhs.Data(), ..., rhs.Data(), ..., result.Data());
return result
}
The following code:
template <typename S, typename T>
struct foo {
void bar();
};
template <typename T>
void foo <int, T>::bar() {
}
gives me the error
invalid use of incomplete type 'struct foo<int, T>'
declaration of 'struct foo<int, T>'
(I'm using gcc.) Is my syntax for partial specialization wrong? Note that if I remove the second argument:
template <typename S>
struct foo {
void bar();
};
template <>
void foo <int>::bar() {
}
then it compiles correctly.
You can't partially specialize a function. If you wish to do so on a member function, you must partially specialize the entire template (yes, it's irritating). On a large templated class, to partially specialize a function, you would need a workaround. Perhaps a templated member struct (e.g. template <typename U = T> struct Nested) would work. Or else you can try deriving from another template that partially specializes (works if you use the this->member notation, otherwise you will encounter compiler errors).
Although coppro mentioned two solutions already and Anonymous explained the second one, it took me quite some time to understand the first one. Maybe the following code is helpful for someone stumbling across this site, which still ranks high in google, like me. The example (passing a vector/array/single element of numericalT as dataT and then accessing it via [] or directly) is of course somewhat contrived, but should illustrate how you actually can come very close to partially specializing a member function by wrapping it in a partially specialized class.
/* The following circumvents the impossible partial specialization of
a member function
actualClass<dataT,numericalT,1>::access
as well as the non-nonsensical full specialisation of the possibly
very big actualClass. */
//helper:
template <typename dataT, typename numericalT, unsigned int dataDim>
class specialised{
public:
numericalT& access(dataT& x, const unsigned int index){return x[index];}
};
//partial specialisation:
template <typename dataT, typename numericalT>
class specialised<dataT,numericalT,1>{
public:
numericalT& access(dataT& x, const unsigned int index){return x;}
};
//your actual class:
template <typename dataT, typename numericalT, unsigned int dataDim>
class actualClass{
private:
dataT x;
specialised<dataT,numericalT,dataDim> accessor;
public:
//... for(int i=0;i<dataDim;++i) ...accessor.access(x,i) ...
};
If you need to partially specialise a constructor, you might try something like:
template <class T, int N>
struct thingBase
{
//Data members and other stuff.
};
template <class T, int N> struct thing : thingBase<T, N> {};
template <class T> struct thing<T, 42> : thingBase<T, 42>
{
thing(T * param1, wchar_t * param2)
{
//Special construction if N equals 42.
}
};
Note: this was anonymised from something I'm working on. You can also use this when you have a template class with lots and lots of members and you just want to add a function.
If you're reading this question then you might like to be reminded that although you can't partially specialise methods you can add a non-templated overload, which will be called in preference to the templated function. i.e.
struct A
{
template<typename T>
bool foo(T arg) { return true; }
bool foo(int arg) { return false; }
void bar()
{
bool test = foo(7); // Returns false
}
};
In C++ 17, I use "if constexpr" to avoid specialize (and rewrite) my method. For example :
template <size_t TSize>
struct A
{
void recursiveMethod();
};
template <size_t TSize>
void A<TSize>::recursiveMethod()
{
if constexpr (TSize == 1)
{
//[...] imple without subA
}
else
{
A<TSize - 1> subA;
//[...] imple
}
}
That avoid to specialize A<1>::recursiveMethod().
You can also use this method for type like this example :
template <typename T>
struct A
{
void foo();
};
template <typename T>
void A<T>::foo()
{
if constexpr (std::is_arithmetic_v<T>)
{
std::cout << "arithmetic" << std::endl;
}
else
{
std::cout << "other" << std::endl;
}
}
int main()
{
A<char*> a;
a.foo();
A<int> b;
b.foo();
}
output :
other
arithmetic