3

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.

user8469759
  • 2,522
  • 6
  • 26
  • 50

2 Answers2

0

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;
Chase R Lewis
  • 2,119
  • 1
  • 22
  • 47
  • For now the max of the two, what would it change in the other case? Is this anyway the general way for metaprogramming? declaring auxiliary struct with such features? – user8469759 Nov 30 '16 at 15:16
  • It used to be the only way. Now you have constexpr options with c++11 and some times type_traits header will have what you need. – Chase R Lewis Nov 30 '16 at 15:19
  • Could you show me also the use of such features? just as a future reference, and I have something to study on. – user8469759 Nov 30 '16 at 15:21
  • in `L > M ? L : M` I would put `(L>M)` in parenthesis as compiler can interpret greater sing as an end of template parameters declaration... – W.F. Nov 30 '16 at 15:50
  • 1
    also it is worth mentioning that `std::max` is constexpr since c++14 so OP actually doesn't have to create his/her own function for this... – W.F. Nov 30 '16 at 15:58
  • You can just use `(L>M?L:M)` directly without any helper structs or functions. – n. m. could be an AI Nov 30 '16 at 16:06
0

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.

skypjack
  • 49,335
  • 19
  • 95
  • 187