功能模板的非依赖默认模板参数是否允许SFINAE?

Xeo*_*Xeo 11 c++ templates sfinae language-lawyer

这里的"非依赖"是指"非依赖于该特定函数模板的任何其他模板参数".

在回答这个问题时,我认为我找到了答案,但根据@Johannes(在我的回答评论中),我在这里误解了标准.采用以下简单示例:

#include <type_traits>

template<class T>
struct X{
  template<class U = typename T::type>
  static void foo(int){}
  static void foo(...){}
};

int main(){
  X<std::enable_if<false>>::foo(0);
}
Run Code Online (Sandbox Code Playgroud)

(现场版.)

以上编译有保证吗?GCC和Clang在这里不同意,可以在实时版本中看到它们之间的切换.有趣的是,GCC接受以下内容:

#include <type_traits>

template<class T>
struct X{
  template<bool = T::f()>
  static void foo(int){}
  static void foo(...){}
};

struct Y{
  static bool f(){ return true; }
};

int main(){
  X<Y>::foo(0);
}
Run Code Online (Sandbox Code Playgroud)

(现场版.)

第二个片段只有foo(int)T包含constexpr静态函数时才会打印f.再说一次,有趣的是,如果你完全f从中删除Y(或通过,int相反),GCC会抱怨缺少一名成员,表明它不允许SFINAE - 这与之前的观察相矛盾.Clang采用所有变化并应用SFINAE,我想知道这是否是标准所保证的.

(FWIW,MSVC与Nov CTP一般同意Clang,但如果功能存在,则在第二个片段崩溃,可能是因为他们没有constexpr.我在这里提交了一个错误报告.)

Joh*_*itb 3

我认为有问题的代码是不正确的,因为当实例化类模板时,除了成员函数和成员函数模板的定义部分和默认参数之外,所有成员声明都被实例化。该标准还定义了函数默认参数何时被精确实例化。

因此默认模板参数会立即实例化。在我看来,此时默认参数旨在包含默认模板参数的可能性非常小,因为没有描述稍后何时实例化此类参数。

这符合“出现在成员类之外的类模板成员定义的模板参数列表中不得指定默认模板参数”的要求。,因为在实例化周围的类模板时无法立即实例化这样的模板参数。