根据模板参数以不同方式重载运算符

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;
};

LIVE

注意运算符重载,不要赋予运算符超出预期的含义。在几乎所有情况下,最好创建具有​​可读名称的函数(为了可维护性)。

你想做什么我认为可以用“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 {}; }
};