这里的“非依赖”是指“不依赖于该特定函数模板的任何其他模板参数”。
在回答this question时,我认为我找到了答案,但根据@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);
}
是否有保证以上编译? 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);
}
如果foo(int)
包含T
静态函数constexpr
,则第二个代码段将仅打印f
。有趣的是,如果您从f
完全删除Y
(或者通过,例如,int
),GCC会抱怨缺少会员,表明它不允许SFINAE - 这与之前的观察相矛盾。 Clang采用所有变体并应用SFINAE,我想知道这是否是标准所保证的。
(FWIW,带有Nov CTP的MSVC通常与Clang一致,但如果该功能存在,则会在第二个代码段崩溃,可能是因为他们没有constexpr
。我提交了一个错误报告{{3} }。)
答案 0 :(得分:3)
我认为有问题的代码是不正确的,因为在实例化类模板时,除了成员函数和成员函数模板的定义部分和默认参数之外,所有成员声明都被实例化。标准还定义了何时精确实例化函数默认参数。
所以默认模板参数会立即被实例化。在我看来,此时默认参数可能包含默认模板参数的可能性非常小,因为没有描述何时这样的参数将是稍后实例化。
这符合要求“不应在模板参数列表中指定默认模板参数,该模板参数列表出现在成员类之外的类模板成员的定义中。” ,因为在实例化周围的类模板时,不会立即实例化这样的模板参数。