当两个模板参数属于同一类型时,如何执行部分专业化?

时间:2019-06-14 10:04:44

标签: c++ templates overload-resolution specialization partial-specialization

如何部分专业化两个模板参数是同一类型。

如何使用第二个函数编写此代码。

#include <utility>
#include <iostream>

template <typename A, typename B>
void Translate(A&& a,B* b){
  // make some translate from a to b
  // b->bvalue=a.av;
  std::cout<<"normal function";
}
//if a and b are same type,
template <typename A>
void Translate(A&& a, A* b) {
  *b = std::forward<A>(a);
  std::cout<<"forward function";
}

int main(int argc, char** argv) {
  int in=0,out=0;
  Translate(in,&out);
  return 0;
}

期望输出“转发功能”。

2 个答案:

答案 0 :(得分:5)

问题在于根本无法调用第二版。您将第一个参数声明为fowarding reference,当传递lvlaue A时将推导为T&。然后,对于第一个参数A推导为int&,对于第二个参数A推导为int,它们发生冲突。

您可以使用std::remove_reference进行类型调整。为了解决以下歧义性问题,您可以使用SFINAE,以便从重载集中排除不需要的专业化知识。

// if A and B are different types
template <typename A, typename B>
std::enable_if_t<!std::is_same_v<std::remove_reference_t<A>, B>> Translate(A&& a,B* b){
  ...
}

// if they're the same type (as A) 
template <typename A>
void Translate(A&& a, std::remove_reference_t<A>* b) {
  ...
}

LIVE

BTW:功能模板不能部分专业化;如您的代码所示,它们只能重载。

答案 1 :(得分:1)

您需要为第一个参数传递右值。下面的两个都打印“转发功能”。

Translate(0, &out);
// or
Translate(std::move(in), &out);

对于Translate(in, out),第二个重载不能一致地推导A类型:第一个参数推导为int&而第二个参数推导为int。 / p>

main.cpp:12:6: note: candidate: 'template<class A> void Translate(A&&, A*)'
 void Translate(A&& a, A* b) {
      ^~~~~~~~~
main.cpp:12:6: note:   template argument deduction/substitution failed:
main.cpp:19:21: note:   deduced conflicting types for parameter 'A' ('int&' and 'int')
   Translate(in, &out);

因此,编译器求助于第一个重载。