具有默认参数的函数的C++部分排序

Bik*_*eev 5 c++ templates c++11

请考虑以下代码:

template <class...>
using void_t = void;

template <class T>
void bar(T){}

template <class T>
void bar(T, void_t<decltype(std::declval<T>().foo())>* = 0) {}

struct A { void foo(); } a;
bar(a); // gives a compiler error on ambiguous call
Run Code Online (Sandbox Code Playgroud)

所以问题是,为什么这些过载模糊不清?为什么第二次重载不被认为是更严格的,比编译器更专业的第二次?

Ric*_*ges 2

实现此目的的常用方法之一是创建同样专业的模板的分离。

#include <utility>
#include <iostream>

template<class T>
struct has_foo_impl
{
  template<class U> static auto test(U* p) -> decltype(p->foo(), void(), std::true_type()); 
  static auto test(...) -> decltype(std::false_type()); 

  using type = decltype(test((T*)nullptr));
};

template<class T> using has_foo = typename has_foo_impl<T>::type;

template <class...>
using void_t = void;

template <class T, std::enable_if_t<not has_foo<T>::value>* = nullptr>
void bar(T){
  std::cout << "not me\n";
}

template <class T, std::enable_if_t<has_foo<T>::value>* = nullptr>
void bar(T) {
  std::cout << "me\n";
}

struct A { void foo(); } a;

int main()
{
    bar(a); // "me"
}
Run Code Online (Sandbox Code Playgroud)