防止隐式模板实例化

cyb*_*rro 6 c++ templates overloading overload-resolution

在像这样的方法过载情况:

struct A
{
  void foo( int i ) { /*...*/ }
  template<typename T> void foo( T t ) { /*...*/ }
}
Run Code Online (Sandbox Code Playgroud)

除非明确命令,否则如何防止模板实例化?:

A a;
a.foo<int>( 1 ); // ok
a.foo<double>( 1.0 ); // ok
a.foo( 1 ); // calls non-templated method
a.foo( 1.0 ); // error
Run Code Online (Sandbox Code Playgroud)

谢谢!

Vit*_*meo 9

您可以引入一个depedent_type防止模板参数推断的结构.

template <typename T>
struct dependent_type
{
    using type = T;
};

struct A
{
  void foo( int i ) { /*...*/ };
  template<typename T> void foo( typename dependent_type<T>::type t ) { /*...*/ }
}
Run Code Online (Sandbox Code Playgroud)

在你的例子中:

a.foo<int>( 1 );      // calls the template
a.foo<double>( 1.0 ); // calls the template
a.foo( 1 );           // calls non-templated method
a.foo( 1.0 );         // calls non-templated method (implicit conversion)
Run Code Online (Sandbox Code Playgroud)

wandbox示例

(此行为在cppreference > 模板参数推导 > 非推导的上下文中进行了解释.)


如果要a.foo( 1.0 )编译错误,则需要约束第一个重载:

template <typename T> 
auto foo( T ) -> std::enable_if_t<std::is_same<T, int>{}> { }
Run Code Online (Sandbox Code Playgroud)

这种技术使得上面的重载foo仅采用int参数:不允许隐式转换(例如floatto int).如果这不是您想要的,请考虑TemplateRex的答案.

wandbox示例

(使用上面的约束函数,a.foo<int>( 1 )调用时两个重载之间存在一种奇怪的交互.我问了一个关于它的问题,因为我不确定引导它的基本规则.)