在像这样的方法过载情况中:
struct A
{
void foo( int i ) { /*...*/ }
template<typename T> void foo( T t ) { /*...*/ }
}
除非明确命令,否则如何阻止模板实例化?:
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
谢谢!
答案 0 :(得分:9)
您可以引入一个阻止template argument deduction的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 ) { /*...*/ }
}
在您的示例中:
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)
(cppreference > template argument deduction > non-deduced contexts解释了此行为。)
如果您想使a.foo( 1.0 )
出现编译错误,您需要约束第一个重载:
template <typename T>
auto foo( T ) -> std::enable_if_t<std::is_same<T, int>{}> { }
此技术使foo
的上述重载仅采用int
个参数:不允许隐式转换(例如float
到int
) 。如果这不是您想要的,请考虑TemplateRex的答案。
(使用上述约束函数,调用a.foo<int>( 1 )
时两个重载之间存在奇怪的交互。我asked a question about it因为我不确定基本规则是什么指导它。)
答案 1 :(得分:1)
到目前为止,最简单的方法是明确删除您不想要的超载:
void foo(double) = delete;
即。有以下明确的例子:
#include <iostream>
struct A
{
void foo(int) { std::cout << __PRETTY_FUNCTION__ << "\n"; }
void foo(double) = delete;
template<typename T>
void foo( T ) {std::cout << __PRETTY_FUNCTION__ << "\n"; }
};
int main()
{
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
}
主要注释掉this prints
中的最后一行中留下最后一行void A::foo(T) [with T = int] void A::foo(T) [with T = double] void A::foo(int)
prog.cc: In function 'int main()': prog.cc:18:16: error: use of deleted function 'void A::foo(double)' a.foo( 1.0 ); // error ^ prog.cc:6:10: note: declared here void foo(double) = delete;
答案 2 :(得分:0)
在底池中添加另一个建议,并且与Vittorio的答案类似,您还可以在签名中添加另一个模板参数:
template <class UserType, class InputType>
void foo(InputType x){...}
然后要使用它,您必须指定第一个模板参数,因为它无法推断。这有一点点优势,能够区分用户想要的内容和传入的内容,在某些情况下可能会有用。
答案 3 :(得分:0)
Halelulah !!!!!!!经过多年的悲伤,我终于找到了答案。因为我知道cpp规则,与定义分开的声明不只是被扔到转储中!!!
// declare template
template <class T> void test();
// declare specialization
template <> // very import to start with this token
void<int> test();
// implicit instantiation
template // if you use this instead, you get instantiation
void<int> test();
我仍然想知道为什么这是必要的。可能是来自Cpp委员会的明智人员的优化。