用c ++中的SFINAE模板推导

时间:2017-07-14 12:04:15

标签: c++ template-meta-programming sfinae

我是SFINAE的新手。我注意到了:

template <typename T> void f(T t) { t.Crash(); } // version 1
void f(...) { } // The sink.
f(1);

template <typename T> void f(const T& t, typename T::iterator* it = nullptr) { } // version 2
void f(...) { } // The sink.
f(1);

在版本2中,由于SFINAE,它不会抛出任何错误,并选择椭圆接收器。但为什么在版本1,编译器会停止并抱怨?

SFINAE仅适用于签名而非身体吗?所以在版本1中,它更喜欢模板函数,但是在什么阶段编译器会停止并抛出错误?

请明确说明编译器关于模板重载解析的处理阶段

1 个答案:

答案 0 :(得分:4)

  

但为什么在版本1,编译器会停止并抱怨?

template <typename T> void f(T t) { t.Crash(); } // version 1
void f(...) { } // The sink.
f(1);

上面f的模板化版本中没有替换失败,因为T可以从调用int推断为f(1)。根据重载决策规则,f<int>(int)f(...)

更受欢迎
template <typename T> void f(const T& t, typename T::iterator* it = nullptr) { } // version 2
void f(...) { } // The sink.
f(1);

那里存在替换失败,因为在将it推导为T之后,编译器需要推导出int的类型。它会替换int代替无效的int::iterator

SFINAE on函数适用于创建有效的功能模板专业化的上下文。

  

SFINAE仅适用于签名而非身体吗?

你可以这样说......在这些有效的代码示例中获取战利品:

//Just the declaration
template <typename T>
void f(T t);

void f(...); 

int main(){
    f(1);   //selects f<int>(int)
}

同时

//just the declarations.
template <typename T> 
void f(const T& t, typename T::iterator* it = nullptr);

void f(...);

int main(){
    f(1);   //selects f(...)
}