c – 模板类中模板类的外部类操作符

我正在尝试在模板类中为模板类编写外部类模板运算符.

我希望以下片段能解释我的意思.

enum MyEnum {};

template <MyEnum a>
class ClassWithTemplateClass {
 public:
    template <bool B> 
    class TemplateClass {
        // ...
    };
};

当我写这样的运算符:

template <MyEnum enumVal, bool B>
auto operator<<(ClassWithTemplateClass<enumVal>::TemplateClass<B> &a, int b) {
    // ...
    return a;
}

编译器返回错误:

错误:’operator<<‘的声明作为非功能 你能告诉我怎么写这个运算符吗?

最佳答案 ClassWithTemplateClass< enumVal> ::是 nested name specifier,而 nested name specifier又是 non-deduced context.由于enumVal是一个出现在作用域解析运算符::左侧的模板参数,因此编译器无法推断出其值.

<<

enum MyEnum { X, Y, Z };

template <MyEnum E>
struct ClassWithTemplateClass
{
    template <bool B> 
    struct TemplateClass
    {
        friend auto& operator<<(TemplateClass& a, int b)
        {
            return a;
        }
    };
};

其中,TemplateClass始终引用ClassWithTemplateClass的特定实例化<?> :: TemplateClass<?>

DEMO

或者(2)在ClassWithTemplateClass中:

enum MyEnum { X, Y, Z };

template <MyEnum E>
struct ClassWithTemplateClass
{
    template <bool B> 
    struct TemplateClass
    {
    };

    template <bool B>
    friend auto& operator<<(TemplateClass<B>& a, int b)
    {
        return a;
    }
};

DEMO 2

或者,(3)您可以为每个预定义的枚举值提供单独的运算符定义(尽管它可以具有比定义为常量更多的值),因此只需要推导出B:

enum MyEnum { X, Y, Z };

template <MyEnum E>
struct ClassWithTemplateClass
{
    template <bool B> 
    struct TemplateClass
    {        
    };
};

template <bool B>
auto& operator<<(ClassWithTemplateClass<X>::TemplateClass<B>& a, int b)
{
    return a;
}

template <bool B>
auto& operator<<(ClassWithTemplateClass<Y>::TemplateClass<B>& a, int b)
{
    return a;
}

template <bool B>
auto& operator<<(ClassWithTemplateClass<Z>::TemplateClass<B>& a, int b)
{
    return a;
}

DEMO 3

,或(4)将模板参数存储为TemplateClass的静态数据成员,并使用它们使操作符SFINAE能够并检索它们的值:

enum MyEnum { X, Y, Z };

template <MyEnum E>
struct ClassWithTemplateClass
{
    template <bool B> 
    struct TemplateClass
    {
        static constexpr MyEnum ClassWithTemplateClass_E = E;
        static constexpr bool TemplateClass_B = B;
    };
};

template <typename T
        , MyEnum E = T::ClassWithTemplateClass_E
        , bool B = T::TemplateClass_B>
auto& operator<<(T& a, int b)
{
    return a;
}

DEMO 4

作为另一种选择,(5)你可以从操作符<<<

enum MyEnum { X, Y, Z };

template <MyEnum E>
struct ClassWithTemplateClass;

template <MyEnum E, bool B>
auto& print(typename ClassWithTemplateClass<E>::template TemplateClass<B>& a, int b);

template <MyEnum E>
struct ClassWithTemplateClass
{
    template <bool B> 
    struct TemplateClass
    {
        friend auto& operator<<(TemplateClass& a, int b)
        {
            return print<E, B>(a, b);
        }
    };
};

template <MyEnum E, bool B>
auto& print(typename ClassWithTemplateClass<E>::template TemplateClass<B>& a, int b)
{
    return a;
}

DEMO 5

点赞