I have a class
template<int n> MyClass<n>
for which I am trying to define the operator &
. I want to be able to perform MyClass&MyClass, but also MyClass&MyClass<1> (or MyClass<1>&MyClass would work for me as well) with a different functionality obviously.
template <size_t n>
struct MyClass
{
//...a lot of stuff
MyClass<n> operator&(const MyClass<n> &other) const;
MyClass<n> operator&(const MyClass<1> &other) const;
}
However, I am not able to compile this, as for the case of n being 1 they collide. I tried adding SFINAE, but apparently I don't understand it well enough to use it in this case.
template <size_t n>
struct MyClass
{
//...a lot of stuff
MyClass<n> operator&(const MyClass<n> &other) const;
std::enable_if_t<n != 1, MyClass<n>> operator&(const MyClass<1> &other) const;
}
Does not work for making sure the case of n being 1 doesn't cause issues. I think it is because SFINAE works for the function template parameters itself, but not the class template parameters.
I believe I could to a specialization of MyClass<1>
, but then I would have to replicate all the contents of MyClass<n>
. Is there any easy solution to this?
CodePudding user response:
SFINAE only works with templates. You can make the 1st operator&
template as:
template <size_t n>
struct MyClass
{
//...a lot of stuff
template <size_t x>
std::enable_if_t<x == n, MyClass<x>> // ensure only MyClass<n> could be used as right operand
operator&(const MyClass<x> &other) const;
// overloading with the template operator&
// non-template is perferred when MyClass<1> passed
MyClass<n> operator&(const MyClass<1> &other) const;
};
CodePudding user response:
You can use constraint (require c 20)
template <size_t n>
struct MyClass
{
MyClass<n> operator&(const MyClass<n> &) const { std::cout << "1\n"; return {}; }
MyClass<n> operator&(const MyClass<1> &) const requires (n!=1) { std::cout << "2\n"; return {}; }
};
CodePudding user response:
Be careful with operator overloading, don't give operators meaning beyond something that can be expected. In almost all cases it is better to create functions with readable names (for maintainability).
What you want to do can I think be done with "if constexpr", example :
#include <utility>
#include <iostream>
template <std::size_t N>
struct MyClass
{
void do_something() const
{
if constexpr (N == 1)
{
std::cout << "behavior 1\n";
}
else
if constexpr (N == 2)
{
std::cout << "behavior 2\n";
}
}
};
int main()
{
MyClass<1> c1;
MyClass<2> c2;
c1.do_something();
c2.do_something();
return 0;
}