Metaprogramming C++, max between two templates parameters - templates

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.

Related

Nested C++ template with variadic

I was wondering if it was possible to have nested C++ template and still be able to access the template values ?
To explain, here is what I currently have:
template <int first, int... tail>
struct ConstIntVector:ConstIntVector<tail...>
{};
template <int first>
struct ConstIntVector<first>
{};
template<int f1, int... t1>
int prod(const ConstIntVector<f1, t1...>, const int* a) {
return f1 * (*a) + prod(ConstIntVector<t1...>(), a+1);
}
This way, I can access the f1 value in my prod function. But I would like to do it like this:
template<ConstIntVector<int f1, int... t1>>
int prod(const int* a) {
return f1 * (*a) + prod<ConstIntVector<t1...>>(a+1);
}
It is possible ?
Partial template specializations aren't allowed for member functions. But you can use a helper struct:
namespace detail
{
template <typename T>
struct prodHelper;
template <int f1, int... t1>
struct prodHelper<ConstIntVector<f1, t1...> >
{
static int eval(const int* a) {
return f1 * (*a) + prodHelper<ConstIntVector<t1...>>::eval(a+1);
}
};
}
template <typename T>
int prod(const int* a) {
return detail::prodHelper<T>::eval(a);
}
Another option would be to utilize ConstIntVector structs to carry useful information:
template <int First, int... Tail>
struct ConstIntVector {
constexpr static int value = First;
using tail = ConstIntVector<Tail...>;
};
template <int First>
struct ConstIntVector<First> {
constexpr static int value = First;
using got_no_tail = void;
};
template <class CIV, typename CIV::tail* = nullptr>
int prod(const int* a) {
return CIV::value * (*a) + prod<typename CIV::tail>(a+1);
}
template <class CIV, typename CIV::got_no_tail* = nullptr>
int prod(const int* a) {
return CIV::value * (*a);
}
Just be aware, that recursion is neither necessary nor desirable to solve these kinds of TMP problems. First, it is better to simply define your vector like this:
template <int... Is>
struct ConstIntVector{};
That way you can have zero length vectors as well, which is convenient in handling edge cases (witness the fact that std::array can be length 0).
Next, lets write our product function. We'll modify it in two ways: first we'll infer the integer by trivially passing our ConstIntVector by value, and second we'll use pack expansions to avoid recursion.
template<int... Is>
int prod(const int* a, ConstIntVector<Is...>) {
int index = 0;
int sum = 0;
int [] temp = {(sum += (a[index++] * Is))...};
return sum;
}
Usage:
std::vector<int> v{1,2,3};
using v2 = ConstIntVector<4,5,6>;
std::cerr << prod(v.data(), v2{});
Live example: http://coliru.stacked-crooked.com/a/968e2f9594c6b292
Link to example of highly optimized assembly: https://godbolt.org/g/oR6rKe.
How about
template<int I>
int prod(const int* a) {
return I * (*a);
}
template<int I, int I2, int... Is>
int prod(const int* a) {
return I * (*a) + prod<I2, Is...>(a + 1);
}

C++ partial template specialization issue with gcc

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.

Return type match with auto and friend function

So I was answering this question: Define friend function template of class template, and I found some "weird" behavior from g++ (5.3) and clang (3.8):
Let's assume the following template:
template<int M>
struct test {
private:
int value;
template<int U, int K>
friend test<K> foo (test<U> const t);
};
template <int M, int N = 2 * M>
test<N> foo (test<M> const t) {
test<N> r;
r.value = t.value;
return r;
}
int main(){
test<1> t;
foo(t);
}
This compile with both compiler (as expected - If this should not compile, feel free to comment and explain why).
If I change things to:
template<int U, int K>
friend auto foo(test<U> const t);
template <int M, int N = 2 * M>
auto foo (test<M> const t) { /* ... */ }
This compile with g++ but not with clang, and if I set one to auto and the other one to a specific value, e.g.:
template<int U, int K>
friend test<K> foo(test<U> const t);
template <int M, int N = 2 * M>
auto foo (test<M> const t) { /* ... */ }
// or:
template<int U, int K>
friend auto foo(test<U> const t);
template <int M, int N = 2 * M>
test<N> foo (test<M> const t) { /* ... */ }
Both compiler reject the code saying that:
error: 'int test<2>::value' is private
My two related questions are:
Which compiler is right for the first case (auto for both declaration/definition)?
Why is not possible to use auto when defining the function and test<K> when declaring the friendship?
Or in one question: What are the rules about auto for friend function declarations when the function is defined outside the class?
Consider [dcl.spec.auto]/13:
Redeclarations or specializations of a function or function template
with a declared return type that uses a placeholder type shall also
use that placeholder, not a deduced type.
I.e. if the friend declaration uses auto and the second declaration does not, they don't match. The other way around is guaranteed by core issue 2081. Finally, if both use auto, the declarations should indeed match as per [temp.over.link]/6, so Clang is incorrect in that case.

Partial template specialization of a single method of a bigger class

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).

C++ automatic type casting : wrong behaviour for a container class

I'm implementing some classes for linear algebra operations on very small constant size vector and matrices.
Currenty, when I do :
MyMathVector<int, 3> a ={1, 2, 3};
MyMathVector<double, 3> b ={1.3, 2.3, 3.3};
std::cout<<"First = "<<a+b<<std::endl;
std::cout<<"Second = "<<b+a<<std::endl;
Then First = {2, 4, 6} and Second = {2.3, 4.3, 6.3}, because the second element is casted to the first element type by the compiler. Is there any "easy" way to provide the same kind of automatic casting like in native C++ : int+double=double, double+int=double ?
Thank you very much.
EDIT :
With the syntax given from answers, I got the operator+ working. But I tried the following syntax, and the compilation fails with the error : expected a type, got ‘std::common_type<T, TRHS>::type’
#include <iostream>
#include <type_traits>
template<class T> class MyClass
{
public:
MyClass(const T& n) : _n(n) {;}
template<class TRHS> MyClass<typename std::common_type<T, TRHS>::type> myFunction(const MyClass<TRHS>& rhs)
{
return MyClass<std::common_type<T, TRHS>::type>(_n*2+rhs._n);
}
T _n;
};
int main()
{
MyClass<double> a(3);
MyClass<int> b(5);
std::cout<<(a.myFunction(b))._n<<std::endl;
}
What is the problem of that syntax ?
Use std::common_type:
template <std::size_t s, typename L, typename R>
MyMathVector<typename std::common_type<L, R>::type, s> operator+(MyMathVector<L, s> const& l, MyMathVector<R, s> const& r)
{
// do addition
}
Ot in case of the member function (in the class body, where T and s are visible):
template <typename TRHS>
MyMathVector<typename std::common_type<T, TRHS>::type, s> operator+(MyMathVector<TRHS, s> const& rhs) const
{
// do addition
}
Use the std::common_type trait to figure out the correct result type for a mixed operation.
The linked page even has an example that's very similar to your case.
Absolutely; use decltype:
template<typename Other>
auto operator+(const MyMathVector<Other, size> &other)
-> MyMathVector<decltype(std::declval<T>() + std::declval<Other>()), size>;
As a non-member operator, it might be better to say what you mean by actually referencing a vector member:
template<typename size, typename L, typename R>
auto operator+(const MyMathVector<L, size> &l, const MyMathVector<R, size> &r)
-> MyMathVector<decltype(l[0] + r[0]), size>;