根据模板参数以不同方式重载运算符
Overloading operator in different ways depending on template argument
我有一个class
template<int n> MyClass<n>
我正在为其定义 operator &
。我希望能够执行 MyClass&MyClass,但也显然具有不同的功能 MyClass&MyClass<1>(或者 MyClass<1>&MyClass 也适用于我)。
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;
}
但是,我无法编译这个,至于n为1的情况,它们会发生冲突。我尝试添加 SFINAE,但显然我不太了解它,无法在这种情况下使用它。
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;
}
无法确保 n 为 1 的情况不会导致问题。我认为这是因为 SFINAE 适用于函数模板参数本身,而不适用于 class 模板参数。
我相信我可以对 MyClass<1>
进行专业化,但我将不得不复制 MyClass<n>
的所有内容。有什么简单的解决方法吗?
SFINAE 仅适用于模板。您可以将第一个 operator&
模板设为:
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;
};
注意运算符重载,不要赋予运算符超出预期的含义。在几乎所有情况下,最好创建具有可读名称的函数(为了可维护性)。
你想做什么我认为可以用“if constexpr”来完成,例如:
#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;
}
可以使用约束(需要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 {}; }
};
我有一个class
template<int n> MyClass<n>
我正在为其定义 operator &
。我希望能够执行 MyClass&MyClass,但也显然具有不同的功能 MyClass&MyClass<1>(或者 MyClass<1>&MyClass 也适用于我)。
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;
}
但是,我无法编译这个,至于n为1的情况,它们会发生冲突。我尝试添加 SFINAE,但显然我不太了解它,无法在这种情况下使用它。
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;
}
无法确保 n 为 1 的情况不会导致问题。我认为这是因为 SFINAE 适用于函数模板参数本身,而不适用于 class 模板参数。
我相信我可以对 MyClass<1>
进行专业化,但我将不得不复制 MyClass<n>
的所有内容。有什么简单的解决方法吗?
SFINAE 仅适用于模板。您可以将第一个 operator&
模板设为:
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;
};
注意运算符重载,不要赋予运算符超出预期的含义。在几乎所有情况下,最好创建具有可读名称的函数(为了可维护性)。
你想做什么我认为可以用“if constexpr”来完成,例如:
#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;
}
可以使用约束(需要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 {}; }
};