C++ 如何强制编译器选择特定的函数专门化

C++ 如何强制编译器选择特定的函数专门化,c++,templates,C++,Templates,例如,我有两门课: class Foo { public: const bool operator==(const Foo&) const; template<class _Ty> const bool operator==(const _Ty&) const; }; class Bar : public Foo { }; 显然,编译器将选择模板函数来计算此表达式,因为变量bar需要转换为Foo&来调用专门的运算符==。但是,当参数是从F

例如,我有两门课:

class Foo {
public:
    const bool operator==(const Foo&) const;

    template<class _Ty>
    const bool operator==(const _Ty&) const;
};

class Bar : public Foo { };
显然,编译器将选择模板函数来计算此表达式,因为变量
bar
需要转换为
Foo&
来调用专门的
运算符==
。但是,当参数是从
Foo
派生的类的实例时(例如添加/删除一些修饰符或其他内容),有没有办法强制编译器(无需将
Bar&
强制转换为
Foo&
)首先选择专门化而不是模板函数

当参数是从Foo派生的类的实例时,有没有办法强制编译器(无需将Bar&强制转换为Foo&)首先选择专门化而不是模板函数

是的,你可以,使用类型特征。具体而言,您可以使用和,如下所示:

template<typename Type>
typename std::enable_if<
    std::is_base_of<Foo, Type>::value,
    const bool
>::type
operator==(const Type&) const { … }

template<typename Type>
typename std::enable_if<
    !std::is_base_of<Foo, Type>::value,
    const bool
>::type
operator==(const Type&) const { … }
模板
typename std::启用\u如果<
std::是::value的_base,
康斯特布尔
>::类型
运算符==(常量类型&)常量{…}
模板
typename std::启用\u如果<
!std::是::value的_base,
康斯特布尔
>::类型
运算符==(常量类型&)常量{…}

基本上可以根据模板参数激活/停用重载

还可以通过添加别名使内容更具可读性:

template<class Type>
using is_fooable = std::is_base_of<Foo, Type>;
模板
使用is_fooable=std::is_base_of;

你可以试着将Bar转换成Foo。@Chnossos是的,我可以。但实际上问题是关于这个表达式,而不是将
Bar&
转换为
Foo&
:)@Chnossos我对问题进行了编辑以澄清问题。在没有强制转换的情况下,我想到的唯一解决方案是更改第一个函数,使其成为第二个函数的特化,用于Foo类型,然后调用您的比较,如
Foo.operator==(bar)
但这有点难看…@Chnossos另一个方法是只保留模板运算符,它将调用私有比较函数(该函数将以与问题中的运算符相同的方式声明,但使用一些伪参数来更改它们的优先级)。但我不知道这是否真的是一个好的解决方案。+1:但我自己,我会将参数标记为分派到
bool equal(Foo const&,std::true_type)
bool equal(t const&,std::false_type)
,因为这样就删除了
实现中不必要的
模板
ing。噢,
const
在错误的位置——你想返回
bool
,但以
const
对象实例为例。@Yakk,你所说的
const
在错误的位置是什么意思呢?你函数的返回值应该是
bool
而不是
const bool
——有非常,返回
const
值类型的有效理由很少。@Yakk,嗯。你为什么要重新分配那个临时对象(由
x==y
返回的对象)?IIRC,在他的一本书中,Scott Meyer推荐了这种做法。如果是基本类型,没有区别。如果是非基本的,
const
阻止有效的
move
退出临时移动(如果移动未被省略)。相反,阻止
operator=
使用左值lhs(模拟基本类型)进行操作。
template<class Type>
using is_fooable = std::is_base_of<Foo, Type>;