【问题标题】:enable_if type is not of a certain template classenable_if 类型不是某个模板类
【发布时间】:2014-09-12 08:10:51
【问题描述】:

TLDR:见最后一段。

我为几个模板类定义了一个operator&,如下所示:

template <typename T>
struct Class {
    Class(T const &t) { }
};

template <typename T_Lhs, typename T_Rhs>
struct ClassAnd {
    ClassAnd(T_Lhs const &lhs, T_Rhs const &rhs) { }
};

template <typename T, typename T_Rhs>
ClassAnd<Class<T>, T_Rhs> operator&(Class<T> const &lhs, T_Rhs const &rhs) {
    return ClassAnd<Class<T>, T_Rhs>(lhs, rhs);
}

template <typename T0, typename T1, typename T_Rhs>
ClassAnd<ClassAnd<T0, T1>, T_Rhs> operator&(ClassAnd<T0, T1> const &lhs, T_Rhs const &rhs) {
    return ClassAnd<ClassAnd<T0, T1>, T_Rhs>(lhs, rhs);
}

int main() {
    Class<int> a(42);
    Class<double> b(3.14);
    auto c = a & b;
}

这很好用。

当我想添加一个 not 操作时会出现问题,该操作仅允许在 and 操作的一侧或另一侧,并且必须返回 ClassAndNot 而不是 ClassAnd 的实例:

template <typename T>
struct ClassNot {
    ClassNot(T const &t) : value(t) { }
    T value;
};

template <typename T_Lhs, typename T_Rhs>
struct ClassAndNot {
    ClassAndNot(T_Lhs const &lhs, T_Rhs const &rhs) { }
};

template <typename T_Lhs, typename T_Rhs>
ClassAndNot<T_Lhs, T_Rhs> operator&(T_Lhs const &lhs, ClassNot<T_Rhs> const &rhs) {
    return ClassAndNot<T_Lhs, T_Rhs>(lhs, rhs.value);
}

template <typename T_Rhs>
ClassNot<T> operator!(T_Rhs const &rhs) {
    return ClassNot<T_Rhs>(rhs);
}

...

auto c = a & !b;

这导致operator&amp; 采用任意右侧返回ClassAndoperator&amp; 采用ClassNot 右侧返回ClassAndNot 之间存在歧义。


问题:

如果std::enable_if 的右侧是ClassNot 中的任何一种类型,如何在此处使用std::enable_if 来禁用第一个operator&amp;?如果一侧是另一侧的模板实例,是否有类似 std::is_same 的东西返回 true?

附言您可以在 ideone 上找到完整的工作示例。

【问题讨论】:

    标签: c++ operator-overloading sfinae enable-if


    【解决方案1】:

    您应该能够为此构建自己的特征:

    template <class T>
    struct IsClassNot : std::false_type
    {};
    
    template <class T>
    struct IsClassNot<ClassNot<T>> : std::true_type
    {};
    
    
    template <typename T, typename T_Rhs>
    typename std::enable_if<!IsClassNot<T_Rhs>::value,
    ClassAnd<Class<T>, T_Rhs>>::type operator&(Class<T> const &lhs, T_Rhs const &rhs) {
        return ClassAnd<Class<T>, T_Rhs>(lhs, rhs);
    }
    

    Live example


    当然,您可以疯狂地进行概括并创建通用特征:

    template <class T, template <class...> class TT>
    struct is_instantiation_of : std::false_type
    {};
    
    template <template <class... > class TT, class... A>
    struct is_instantiation_of<TT<A...>, TT> : std::true_type
    {};
    
    template <class T>
    using IsClassNot = is_instantiation_of<T, ClassNot>;
    

    Live example

    【讨论】:

    • 您的第二个示例正是我想要的(但由标准库提供)。我将使用第一个示例以使事情变得更简单。谢谢!
    • @zennehoy 我猜标准库没有提供它的原因之一是,对于采用任何非类型或模板模板参数的类模板,没有办法完全编写它.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-30
    • 2012-01-22
    • 1970-01-01
    • 2012-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多