VS2013中的SFINAE

Qin*_*Yun 4 c++ visual-studio c++11

我有一个功能模板forwardMaybeNull.我希望如果它不是a nullptr,它可以转发第一个参数,如果第一个参数是a,则返回第二个参数nullptr.

template <typename T, typename U,
          std::enable_if_t<std::is_same<T, std::nullptr_t>::value>...>
U&& forwardMaybeNull(std::nullptr_t, U&& rvalue_default) {
  return std::move(rvalue_default);
}

template <typename T, typename U,
          std::enable_if_t<!std::is_same<T, std::nullptr_t>::value>...>
T&& forwardMaybeNull(std::remove_reference_t<T>& arg, U&&) {
  return static_cast<T&&>(arg);
}

template <typename T, typename U,
          std::enable_if_t<!std::is_same<T, std::nullptr_t>::value>...>
T&& forwardMaybeNull(std::remove_reference_t<T>&& arg, U&&) {
  return static_cast<T&&>(arg);
}

template <typename T>
void Bar(T&&) {}

template <typename T>
void Foo(T&& t) {
    Bar(forwardMaybeNull<T>(t, [](){}));
}

int main() {
  Foo(nullptr);
}
Run Code Online (Sandbox Code Playgroud)

它在gcc4.8中运行良好,但VS2013表示这是"对重载函数的模糊调用".

R. *_*des 5

我建议在VS2013中避免使用任何非平凡的模板代码.地狱,即使是我称之为琐碎的模板代码也给了我麻烦.

对于这种情况,您可以使用部分特化类模板的旧技术.即使在海湾合作委员会,我也会这样做.像下面这样的东西.

namespace detail {

template <typename T, typename U>
struct forwarderMaybeNull {
  using result_type = T&&;
  static T&& call(std::remove_reference_t<T>& arg, U&&) {
    return static_cast<T&&>(arg);
  }

  static T&& call(std::remove_reference_t<T>&& arg, U&&) {
    return static_cast<T&&>(arg);
  }
};

template <typename U>
struct forwarderMaybeNull<nullptr_t, U> {
  using result_type = U&&;
  static U&& call(std::nullptr_t, U&& rvalue_default) {
    return std::move(rvalue_default);
  }
};

}

template <typename T, typename U>
typename detail::forwarderMaybeNull<T, U>::result_type forwardMaybeNull(
    std::remove_reference_t<T>& arg, U&& u) {
  return detail::forwarderMaybeNull<T, U>::call(std::forward<T>(arg),
                                                std::forward<U>(u));
}
template <typename T, typename U>
typename detail::forwarderMaybeNull<T, U>::result_type forwardMaybeNull(
    std::remove_reference_t<T>&& arg, U&& u) {
  return detail::forwarderMaybeNull<T, U>::call(std::forward<T>(arg),
                                                std::forward<U>(u));
}
Run Code Online (Sandbox Code Playgroud)