I have the following class;
template<int N, int M, int K>
class BaumWelch
{
//lots of stuff
const TransitionMatrixTemplate<N, M> randomA()
{ //.... }
}
now I would like to specialize the method randomA for N=1. How can I do it?
I tried following this question: Template specialization of a single method from a templated class, but it doesn't seem to work with partial specialization. This question: C++ partial method specialization seems more relevant, but it suggest specializing the whole class (which is quite big in my case). Is it possible to specialize the whole class, but actually specialize only this one method?
I would like to specialize the method randomA for N=1. How can I do it?
You've discovered that partial specialization for functions is not allowed.
However, you can fully specialize a "detail" implementation of the code.
template<int TheN>
detail_randomA();
const TransitionMatrixTemplate<N, M> randomA()
{
return detail_randomA<N>();
}
And outside the class declaration:
template<int N, int M, int K>
template<int TheN>
BaumWelch<N,M,K>::detail_randomA()
{
//lots of stuff when N != 1
}
template<int N, int M, int K>
template<>
BaumWelch<N,M,K>::detail_randomA<1>()
{
//lots of stuff when N == 1
}
You can't partially specialize function templates, but you can pass the work off to class templates. Here's a fully working example:
#include<iostream>
using namespace std;
// This first template isn't important, it's just the return value from your function
template <int N, int M>
struct TransitionMatrixTemplate {
void print_me() const {
cout << N << ',' << M << endl;
}
};
// We need to announce the existence of the BaumWelch class template early here,
// in order that it can appear in the signature of our impl_randomA class.
template<int N, int M, int K>
struct BaumWelch;
// Now, the first important bit of code. The default implementation
template<int N, int M, int K>
struct impl_randomA {
static TransitionMatrixTemplate<N,M> f(BaumWelch<N,M,K> * This) {
return TransitionMatrixTemplate<N,M>();
}
};
// Next, is the partially specialized version.
template<int M, int K>
struct impl_randomA<1,M,K> {
static TransitionMatrixTemplate<1,M> f(BaumWelch<1,M,K> * This) {
cout << "<Special for N=1> ";
return TransitionMatrixTemplate<1,M>();
}
};
// Finally, The BaumWelch class and its call out to impl_randomA.
template<int N, int M, int K>
struct BaumWelch {
const TransitionMatrixTemplate<N, M> randomA() {
return impl_randomA<N,M,K> :: f(this);
}
};
int main() {
BaumWelch<2,3,4>() . randomA() . print_me();
BaumWelch<1,3,4>() . randomA() . print_me();
}
The short answer is "you don't".
A way to make it easy to do what you want to do (have randomA act differently for N=1) would be to stuff const TransitionMatrixTemplate<N, M> randomA() into a CRTP parent, then partially specialize that for N=1.
template<typename D, int N, int M, int K>
struct Bob_Base {
static_assert( std::is_base_of< D, Bob_Base<D, N, M, K> >::value, "D must be derived from Bob_Base" );
D* self() { return static_cast<D*>(this);
D const* self() const { return static_cast<D*>(this);
const TransitionMatrixTemplate<N, M> randomA()
{
// use self()-> instead of this-> in here to access Bob methods and date
}
};
template<typename D,int M, int K>
struct Bob_Base< D, 1, M, K > {
static_assert( std::is_base_of< D, Bob_Base<D, N, M, K> >::value, "D must be derived from Bob_Base" );
D* self() { return static_cast<D*>(this);
D const* self() const { return static_cast<D*>(this);
const TransitionMatrixTemplate<1, M> randomA()
{ /* N=1 version */ }
};
template<int N, int M, int K>
struct Bob : Bob_Base<Bob<N, M, K>, N, M, K>
{
//lots of stuff, but no TransitionMatrixTemplate
}
this is only important if the code where N==1 cannot compile (or vice versa).
Related
I would like to define a class template (hereafter called C) which takes a reference to an object of an to-be instantiated class template (hereafter called S) as template parameter. The objective is that C can be fully instantiated with one template argument.
S is a class template on its own which has one integral type template parameter. The C class template shall be instantiated using a reference to an object of any instantiation of S.
This is what I am trying to achieve:
template<int I> struct S {
int get() { return 42 + I; }
};
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ my desperate attempt
template< typename S<int I>::template & n>
struct C {
int get() {
return n.get();
}
};
S<42> s;
int main()
{
C<s> c;
return c.get();
}
The compiler I am using supports GNU++11 or older.
In C++17, you might do
template<int I> struct S { int get() { return 42 + I; } };
template <auto& n>
struct C;
template <int I, S<I>& n>
struct C<n>
{
int get() { return n.get(); }
};
S<42> s;
int main()
{
C<s> c;
return c.get();
}
Demo.
Before C++17, template <auto& n> struct C; has to be replaced. for example by
template <typename T, T& n> struct C;
template <typename T, T& n>
struct C;
template <int I, S<I>& n>
struct C<S<I>, n>
{
int get() { return n.get(); }
};
S<42> s;
#define AUTO(x) decltype(x), x
int main()
{
C<S<42>, s> c;
// C<AUTO(s)> c;
return c.get();
}
Demo
There is no way that I know in C++11 that will allow you to change just the template parameters to do what you want. What you can do though is not have a non-type template parameter, but just a type, and add a constructor to C that takes the reference to the desired object as a parameter:
template<typename T>
struct C {
C(T &t): t(t) {}
int get() {
return t.get();
}
private:
T &t;
};
Then you could declare c as follows:
C<decltype(s)> c(s);
However, it is of course not so nice to have to repeat yourself like that, so the trick is to make a templated function that will construct a C of the right type for you:
template<typename T>
C<T> make_C(T &t) {
return C<T>(t);
}
And then you can write:
auto c = make_C(s);
This is not the answer. But maybe this helps somebody who stumbled upon this question or even help somebody to actually find the answer.
In contrast to the original question I added the static member variable S.i.
template<int I> struct S {
static constexpr int i = I;
int get() { return 42 + I; }
};
template<int I, S<I>& n> struct C
{
int get() {
return n.get();
}
};
S<42> s;
int main()
{
C<s.i, s> c;
return c.get();
}
This is not the answer, because still two template arguments are required in order to instantiate the class template C.
This compiles with C++11.
I want to design a m x n matrix class (as a template parameterized by m rows and n columns) and need to specialize it in order to equip it with operations that are mathematically possible based on three conditions:
m > n
m == n
no specialization for m < n, that is, basic or default implementation
The template signature is simply:
template <size_t m, size_t n, typename T = double> class MatrixBase
{
....
};
How do I do that? Can it be done with type traits? Or should I use std::conditional<> or std::enable_if<> ?. Conceptually, what I want to accomplish is to add methods to a class but without subclassing it and creating any inheritance hierarchy. The derivation tree I want to use for other things, namely the data storage within the matrix.
So I would like to have a matrix that if declared as for instance MatrixBase<4, 4, float> has (by virtue of specialization) a method called inverse (), while matrices declared with m <> n don't. Similarly, extra methods for matrices with m > n.
It can be done with std::enable_if:
template <size_t m, size_t n, typename T = double>
class MatrixBase
{
public:
template <typename T1 = T>
std::enable_if_t<m == n, MatrixBase<m, m, T1>> inverse() const
{
// Calculate inverse
return{};
}
};
int main(int argc, const char *argv[])
{
auto msquare = MatrixBase<4, 4>();
auto mrect = MatrixBase<4, 3>();
msquare.inverse(); // No error
mrect.inverse(); // Compilation error
return 0;
}
For partial specialization you can also use enable_if:
template <size_t m, size_t n, typename T = double, typename E = void>
class MatrixBase
{
public:
template <typename T1 = T>
std::enable_if_t<m == n, MatrixBase<m, m, T1>> inverse() const
{
// Calculate inverse
return{};
}
};
template <size_t m, size_t n, typename T>
class MatrixBase<m, n, T, std::enable_if_t<m == n, void>>
{
public:
static bool m_equals_n()
{
return true;
}
};
template <size_t m, size_t n, typename T>
class MatrixBase<m, n, T, std::enable_if_t<n < m, void>>
{
public:
static bool m_greater_than_n()
{
return true;
}
};
template <size_t m, size_t n, typename T>
class MatrixBase < m, n, T, std::enable_if_t<m < n, void>>
{
public:
static bool m_less_than_n()
{
return true;
}
};
int main(int argc, const char *argv[])
{
auto msquare = MatrixBase<4, 4>();
auto m_4_3 = MatrixBase<4, 3>();
auto m_3_4 = MatrixBase<3, 4>();
msquare.m_equals_n();
//msquare.m_greater_than_n(); // Compilation error
m_4_3.m_greater_than_n();
m_3_4.m_less_than_n();
return 0;
}
For example, I have a class:
class A
{
enum {N = 5};
double mVariable;
template<class T, int i>
void f(T& t)
{
g(mVariable); // call some function using mVariable.
f<T, i+1>(t); // go to next loop
}
template<class T>
void f<T, N>(T& t)
{} // stop loop when hit N.
};
Partial specialization is not allowed in function template. How do I work around it in my case?
I slightly changed the example of Arne Mertz, like:
template<int n>
struct A
{
enum {N = n};
...
};
and use A like:
A<5> a;
The I cannot compile on Visual Studio 2012. Is it a compiler bug or something else? It is quite strange.
EDIT: Checked. It is a Visual Studio bug. :(
I think Nim gives the most simple way to implement it.
The most straight forward solution is to use a template class instead of a function:
class A
{
enum {N = 5};
double mVariable;
template <class T, int i>
struct fImpl {
static_assert(i<N, "i must be equal to or less than N!");
static void call(T& t, A& a) {
g(a.mVariable);
fImpl<T, i+1>::call(t, a);
}
};
template<class T>
struct fImpl<T,N> {
static void call(T&, A&) {} // stop loop when hit N.
};
public:
template<class T, int i>
void f(T& t)
{
fImpl<T, i>::call(t,*this);
}
};
Example link
You can define a helper class:
template <int i, int M>
struct inc_up_to
{
static const int value = i + 1;
};
template <int i>
struct inc_up_to<i, i>
{
static const int value = i;
};
template<class T, int i>
void f(T& t)
{
if (i < N) {
g(mVariable); // call some function using mVariable.
f<T, inc_up_to<i, N>::value>(t);
}
}
It stops the compile-time recursion by making f<T, N> refer to f<T, N>, but that call is avoided by the run-time condition, breaking the loop.
A simplified and more robust version of the helper (thanks #ArneMertz) is also possible:
template <int i, int M>
struct inc_up_to
{
static const int value = (i >= M ? M : i + 1); // this caps at M
// or this:
static const int value = (i >= M ? i : i + 1); // this leaves i >= M unaffected
};
This doesn't even need the partial specialisation.
With c++11 support, you can do the following:
#include <iostream>
#include <type_traits>
using namespace std;
struct A
{
enum {N = 5};
double mVariable;
void g(int i, double v)
{ std::cout << i << " " << v << std::endl; }
template<int i, class T>
typename enable_if<i >= N>::type f(T& t)
{} // stop loop when hit N.
template<int i, class T>
typename enable_if<i < N>::type f(T& t)
{
g(i, mVariable); // call some function using mVariable.
f<i+1, T>(t); // go to next loop
}
};
int main(void)
{
A a;
int v = 0;
a.f<0>(v);
}
Main reason I like is that you don't need any of the cruft as required by the previous answers...
You can emulate partial specialization of function template with function overloading:
#include <type_traits>
class A
{
enum {N = 5};
double mVariable;
// ...
void g(double)
{
// ...
}
public:
template<class T, int i = 0>
void f(T& t, std::integral_constant<int, i> = std::integral_constant<int, i>())
{
g(mVariable);
f(t, std::integral_constant<int, i + 1>());
}
template<class T>
void f(T& t, std::integral_constant<int, N>)
{
}
};
Example of using:
A a;
int t = 0;
a.f(t);
a.f(t, std::integral_constant<int, 2>()); // if you want to start loop from 2, not from 0
It is a C++11 solution, however (not so much because of std::integral_constant class, but because of default template parameter of function template). It can be made shorter using some additional C++11 features:
template<int i>
using integer = std::integral_constant<int, i>;
template<class T, int i = 0>
void f(T& t, integer<i> = {})
{
g(mVariable);
f(t, integer<i + 1>());
}
template<class T>
void f(T& t, integer<N>)
{
}
This question already has answers here:
How to pass a template function in a template argument list
(2 answers)
Closed 6 years ago.
For the life of me, I can't get this simple piece of arcane template magic to work:
template<typename T, int a, int b>
int f(T v){
return v*a-b; // just do something for example
}
template<typename T, int a, int b, template<typename,int,int> class func>
class C{
int f(){
return func<T,a,b>(3);
}
};
int main(){
C<float,3,2, f> c;
}
Is this possible to do without involving functors?
f is supposed to be a class - you have a function.
See below:
// Class acts like a function - also known as functor.
template<typename T, int a, int b>
class f
{
int operator()(T v)
{
return v*a-b; // just do something for example
}
};
template<typename T, int a, int b, template<typename,int,int> class func>
class C
{
int f()
{
return func<T,a,b>(3);
}
};
int main()
{
C<float,3,2, f> c;
}
... And the adapted version if you need to port legacy code (Adapts the function to a class template):
#include <iostream>
template<typename T, int a, int b>
int f(T v)
{
std::cout << "Called" << std::endl;
return v*a-b; // just do something for example
}
template<typename T, int a, int b, template<typename,int,int> class func>
struct C
{
int f()
{
return func<T,a,b>(3);
}
};
template <class T, int a, int b>
struct FuncAdapt
{
T x_;
template <class U>
FuncAdapt( U x )
: x_( x )
{}
operator int() const
{
return f<T,a,b>( x_ );
}
};
int main()
{
C<float,3,2, FuncAdapt > c;
c.f();
}
You can solve it through a little trickery:
template<typename T, int a, int b>
int f(T v){
return v*a-b; // just do something for example
}
template<typename T, int, int>
using func_t = int (*)(T);
template<typename T, int a, int b, func_t<T, a, b> func>
class C{
int f(){
return func(3);
}
};
C<float,3,2, f<float, 3, 2>> c;
First you need a type-alias for the function (func_t above), and you unfortunately need to duplicate the template arguments in the declaration of c.
No, it's not. Even the syntax:
template <typename T, int a, int b, template <typename, int, int> class func>
^^^^^
shows that an argument for a template template parameter must be a class template.
The reason your compiler is complaining is that you're passing a function (f) as a class to the last template parameter for class C.
Since you cannot pass a function as a template parameter, you should use function pointers or functors. And functors are definitely the cleaner way to do this.
So, although it's possible to achieve what you want without using functors, you really shouldn't try to.
If you want to use function pointers you will be looking at something like this:
template<typename T, int a, int b, int (*func)(T)>
class C{
int f(){
return (*func)(3);
}
};
int main(){
C< float,3,2,&f<float,3,2> > c;
}
In that case I don't think you would be able to eliminate the code duplication in the declaration of c, but I might be wrong.
I am creating a templated class D<N>, with a method (operator(), in this case) that returns different types, depending on the value of N.
I could only make this work by creating two separate class declarations, but this came at the cost of a lot of code duplication. I also tried to create a common base class to throw the common stuff into, but I couldn't get the constructor to inherit right and don't know how idiomatic that would be as well...
#include <cstdio>
template <int N>
struct D{
int s;
D(int x):s(x){}
int yell(int x){
printf("N=%d, %d\n", N, s+x);
return s+x;
}
D<N-1> operator()(int x){
D<N-1> d(yell(x));
return d;
}
};
template <>
struct D<1>{
int s;
D(int x): s(x){}
int yell(int x){
printf("N=%d, %d\n", 1, s+x);
return s+x;
}
int operator()(int x){
return yell(x);
}
};
int main()
{
D<2> f(42);
printf("%d\n", f(1)(2));
return 0;
}
How can I make my code better looking?
You can use the Curiously Recurring Template Pattern.
template<int N, template<int> typename D> struct d_inner {
D<N-1> operator()(int x) {
return D<N-1>(static_cast<D<N>*>(this)->yell(x));
}
};
template<template<int> typename D> struct d_inner<1, D> {
int operator()(int x) {
return static_cast<D<1>*>(this)->yell(x);
}
};
template <int N> struct D : public d_inner<N, D> {
int s;
D(int x):s(x){}
int yell(int x){
printf("N=%d, %d\n", N, s+x);
return s+x;
}
};
Not that I see the utility- or purpose- of this particular object being templated, it could easily not be.
I'm not sure it is better looking: but it avoids source code duplication :
// Find a name for this ...
template<int N, template<int M> class X>
struct foo {
typedef X<N> type;
};
template< template<int M> class X >
struct foo<0,X> {
typedef int type;
};
template <int N>
struct D{
int s;
D(int x):s(x){}
int yell(int x){
printf("N=%d, %d\n", N, s+x);
return s+x;
}
typename foo<N-1,D>::type
operator()(int x){
return typename foo<N-1,D>::type(yell(x));
}
};