我有以下代码:
#include <type_traits>
#include <memory>
class CDelegateCore {};
class CDelegate : public CDelegateCore {};
class CEvent
{
private:
/// Simple empty enumeration used for enable_if test.
enum class enabler_t {};
template<typename T>
using EnableIf = typename std::enable_if<T::value, enabler_t>::type;
public:
CEvent() {}
~CEvent() {}
void operator += (CDelegateCore* func) {}
template<typename T, typename Deleter, EnableIf<std::is_base_of<CDelegateCore, T>> = enabler_t{}>
void operator += (std::unique_ptr<T, Deleter> const& func) { *this += func.get(); }
};
int main()
{
std::unique_ptr<CDelegate> testdel;
// ... initialize testdel ...
CEvent EVENT;
EVENT += testdel;
}
此处的目标是,当CDelegate
拥有std::unique_ptr
时,+=
使用CEvent
的{{1}}重载将被调用,将推导std::enable_if
内的模板参数。
此代码在GCC和Clang中正常工作,但在MSVC12中失败。它无法解决该功能。谁能告诉我为什么?我最初没有为unique_ptr删除器设置模板参数,并且它有效,但是我不确定C ++中有关使用默认嵌套模板参数的类型推导的规则。
答案 0 :(得分:3)
我不确定这一点,但我相信这是因为VS2013缺乏表达SFINAE支持。如果将enable_if
表达式移动到operator+=
template<typename T, typename Deleter>
typename std::enable_if<std::is_base_of<CDelegateCore, T>::value>::type
operator += (std::unique_ptr<T, Deleter> const& func) { *this += func.get(); }
您可以使用EnableIf
别名,将第二个模板参数更改为void
,或者只使用std::enable_if_t
(gcc和clang上需要-std=c++1y
)。
答案 1 :(得分:0)
VS2013支持SFINAE或至少大部分。 改变
template<typename T, typename Deleter, EnableIf<std::is_base_of<CDelegateCore, T>> = enabler_t{}>
到
template<typename T, typename Deleter, class = EnableIf<std::is_base_of<CDelegateCore, T>>>