I am trying to calculate GCD, at compile time using template partial specialization.
Following code works fine with clang3.8 but not with gcc7.1. With GCC, it's going into recursive template instantiation without realizing terminating case.
template <int N, int M>
struct GCD{
static const int value = (N>M)? GCD<N%M, M>::value : GCD<N, M%N>::value;
};
template <int M>
struct GCD<0, M>{
static const int value = M;
};
template <int M>
struct GCD<M, 0>{
static const int value = M;
};
int main()
{
static_assert(GCD<12,15>::value == 3, "Error");
}
Who is behaving sane here?
If you want to solve the problem, I propose the following improvement
template <int N, int M, bool = (M != 0) && (N != 0) && (N > M)>
struct GCD;
template <int N, int M>
struct GCD<N, M, true>
{ static constexpr int value { GCD<N%M, M>::value }; };
template <int N, int M>
struct GCD<N, M, false>
{ static constexpr int value { GCD<N, M%N>::value } ; };
template <int M>
struct GCD<0, M, false>
{ static constexpr int value { M }; };
template <int M>
struct GCD<M, 0, false>
{ static constexpr int value { M }; };
If you want to know if is right g++ or clang++, well... I don't know what, exactly, a compiler can or must do in this circumstances so... I don't know.
Precisely, I don't know, when N > M and a compiler encounter,
static const int value = (N>M)? GCD<N%M, M>::value : GCD<N, M%N>::value;
if the compiler must (or can) implement only GCD<N%M, M> or if must (or can) implement GCD<N, M%N> also.
Anyway, if I'm not wrong, clang++ implement only GCD<N%M, M> where g++ implement both.
My improvement is tailored to avoid this problem.
Related
I haven't been doing this for a while. I basically have a class
template <int L>
class MyInteger {
//code
};
And specifically I'd like to implement something like (as a method)
template <int L, int M, int N>
MyInteger<N> MyInteger<L>::operator+(const MyInteger<M>& x) const;
But I want to restrict N to be the max(L,M) is there a way to achieve that using template metaprogramming? I was thinking the use of enable_if and maybe SFINAE could allow me to achieve what I want, but I'm not entirely sure how to do that.
Do you just want it to be the max of the two? Or do you want it to be no more than the max of the two? If you want it to always be the max I'd create a utility struct like below and set N as
template<int L,int M>
struct MaxInteger
{
public:
static const int value = L > M ? L : M;
};
Then implement it like this.
template<int L, int M>
MyInteger<MaxInteger<L,M>::value> MyInteger<L>::operator+(const MyInteger<M>& x) const;
Edit: As requested a constexpr implementation.
constexpr int constMax(constexpr int a,constexpr int b) {return a > b ? a : b;}
Then implement like this
template<int L, int M>
MyInteger<constMax(L,M)> MyInteger<L>::operator+(const MyInteger<M>& x) const;
or you can do it without the struct
template<int L, int M>
MyInteger<L > M ? L : M> MyInteger<L>::operator+(const MyInteger<M>& x) const;
In C++14 (as you tagged the question) you can simply do this:
#include <type_traits>
template <int L>
class MyInteger {};
template <int L, int M>
constexpr auto operator+(const MyInteger<L> &lhs, const MyInteger<M> &rhs) {
return MyInteger<(L > M ? L : M)>{};
}
int main() {
constexpr MyInteger<0> m1;
constexpr MyInteger<1> m2;
static_assert(std::is_same<decltype(m1 + m2), MyInteger<1>>::value, "!");
}
That is, use the auto return type and let the compiler deduce it for you.
Then, in the body of the function, you can pick the max value up and create the right type.
If you prefer to be explicit about the return type, another possible solution is this:
template <int L, int M>
constexpr MyInteger<(L > M ? L : M)> operator+(const MyInteger<L> &lhs, const MyInteger<M> &rhs) {
return {};
}
No need to use sfinae anywhere.
I have a template class with some integers as arguments. One static const integer (call it Length) of this class needs to be calculated based on the arguments. The calculation does need a loop (as far as I know) so a simple expression won't help.
static int setLength()
{
int length = 1;
while (length <= someTemplateArgument)
{
length = length << 1;
}
return length;
}
The returned length should be used to init Length. Lengthis used as a fixed length of an array so I need it to be constant.
Is there a solution for this issue? I know that constexp could help but I can't use C11 or later.
Using metaprogramming. Implementation of C++11 enable_if taken from cppreference.com
#include <iostream>
template<bool B, class T = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> { typedef T type; };
template <int length, int arg, typename = void>
struct length_impl
{
static const int value = length_impl<(length << 1), arg>::value;
};
template <int length, int arg>
struct length_impl<length, arg, typename enable_if<(length > arg)>::type>
{
static const int value = length ;
};
template <int arg>
struct length_holder
{
static const int value = length_impl<1, arg>::value;
};
template<int n>
struct constexpr_checker
{
static const int value = n;
};
int main()
{
std::cout << constexpr_checker< length_holder<20>::value >::value;
}
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>)
{
}
Consider the following metafunction for an integral pow (it is just an example) :
class Meta
{
template<int N, typename T> static constexpr T ipow(T x)
{
return (N > 0) ? (x*ipow<N-1>(x))
: ((N < 0) ? (static_cast<T>(1)/ipow<N>(x))
: (1))
}
};
How to write the stop condition for such a function ?
Anytime you ask yourself "how to simulate partial specialization for functions", you can think "overload, and let partial ordering decide what overload is more specialized".
template<int N>
using int_ = std::integral_constant<int, N>;
class Meta
{
template<int N, typename T> static constexpr T ipow(T x)
{
return ipow<N, T>(x, int_<(N < 0) ? -1 : N>());
}
template<int N, typename T> static constexpr T ipow(T x, int_<-1>)
{
// (-N) ??
return static_cast<T>(1) / ipow<-N>(x, int_<-N>());
}
template<int N, typename T> static constexpr T ipow(T x, int_<N>)
{
return x * ipow<N-1>(x, int_<N-1>());
}
template<int N, typename T> static constexpr T ipow(T x, int_<0>)
{
return 1;
}
};
I think you wanted to pass -N instead of N at the comment-marked position.
A simple version might go like this:
template <typename T, unsigned int N> struct pow_class
{
static constexpr T power(T n) { return n * pow_class<T, N - 1>::power(n); }
};
template <typename T> struct pow_class<T, 0>
{
static constexpr T power(T) { return 1; }
};
template <unsigned int N, typename T> constexpr T static_power(T n)
{
return pow_class<T, N>::power(n);
}
Usage:
auto p = static_power<5>(2); // 32
Just use static members in a class template and specialize the class template. You might want to create a forwarding function template for convenience, though.
I've a code smth like this:
template<int N, typename T>
class XYZ {
public:
enum { value = N };
//...
}
Is there a way to restrict N in some way? Specifically I want to allow compilation only if N is divided by some number, let's say 6.
So it turned out to be not just a type restriction.
Preferred way is to do this without Boost.
One C++03 approach:
template<int X, int Y>
struct is_evenly_divisible
{
static bool const value = !(X % Y);
};
template<int N, typename T, bool EnableB = is_evenly_divisible<N, 6>::value>
struct XYZ
{
enum { value = N };
};
template<int N, typename T>
struct XYZ<N, T, false>; // undefined, causes linker error
For C++11, you can avoid some boilerplate and give a nicer error message:
template<int N, typename T>
struct XYZ
{
static_assert(!(N % 6), "N must be evenly divisible by 6");
enum { value = N };
};
I leave this here for the future, since I couldn't find a good example online at the time of posting.
The C++20 way with concepts:
template<int X, int Y>
concept is_evenly_divisible = X % Y == 0;
template <int N, int M> requires is_evenly_divisible<N, M>
struct XYZ
{
enum class something { value = N };
};
XYZ<12, 6> thing; // OK
//XYZ<11, 6> thing; // Error
Or even shorter:
template <int N, int M> requires (N % M == 0)
struct XYZ
{
enum class something { value = N };
};