如何避免对非构造函数进行隐式强制转换?
我有一个以整数为参数的函数,
但是这个函数也会接受字符、布尔值和长整型。
我相信它是通过隐式地强制转换它们来做到这一点的。
如何避免这种情况,使函数只接受匹配类型的参数,否则将拒绝编译?
有一个关键字“explicit”,但它不适用于非构造函数。:
我该怎么办?
下面的程序将编译,尽管我不希望它编译:
#include <cstdlib>
//the function signature requires an int
void function(int i);
int main(){
int i{5};
function(i); //<- this is acceptable
char c{'a'};
function(c); //<- I would NOT like this to compile
return EXIT_SUCCESS;
}
void function(int i){return;}
- 请务必指出任何术语和假设的误用
9条答案
按热度按时间js81xvg61#
定义与所有其他类型匹配的函数模板:
这是因为具有直接匹配的非模板函数总是首先被考虑,然后才考虑具有直接匹配的函数模板--所以永远不会使用
function<int>
,但是对于其他任何函数,比如char,都会使用function<char>
--这会导致编译错误:错误:
这是C++03的方法:
zyfwsgd62#
不能直接使用,因为
char
会自动升级为int
。不过,您可以使用一个技巧:创建一个以
char
为参数的函数,但不实现它。它可以编译,但会得到一个链接器错误:使用
char
参数调用函数将中断生成。参见http://ideone.com/2SRdM
术语:非构造函数?你是指不是构造函数的函数吗?
hiz5n14c3#
8年后(PRE-C++20,参见编辑):
如果您不介意模板函数(您可能会介意),最现代的解决方案是使用
std::enable_if
和std::is_same
的模板函数。即:
编辑(c++20)
我最近转向了c20,我相信有一个更好的方法。**如果你的团队或你不使用c20,或者不熟悉新的概念库,不要使用这个。**这是更好的,并且是新的c++20标准和新特性的作者所概述的预期方法(阅读Bjarne Stroustrup here所写的论文。
小编辑(概念的不同模式)
下面是一个更好的方法,因为它解释了你的理由,有一个显式的int。如果你经常这样做,并希望有一个好的模式,我会这样做:
小编2(最后我承诺)
实现这种可能性的另一种方法是:
brccelvz4#
下面是一个通用的解决方案,如果使用int以外的任何值调用
function
,则会在编译时导致错误它的工作原理是允许任何类型的参数起作用,但使用
is_int
作为类型级 predicate 。is_int
的泛型实现有一个false值,但int类型的显式特化有一个true值,以便静态Assert保证参数完全具有int
类型,否则会出现编译错误。u5rb5r595#
也许你可以使用一个结构体来使第二个函数私有化:
这将无法编译:
sg2wtvxw6#
对于C14(我相信是C11),你也可以通过重载右值引用来禁用复制构造函数:
例如:假设你有一个
Binding<C>
基类,其中C
是Constraint
基类,或者是继承类。假设你在一个向量中按值存储Binding<C>
,你传递了一个引用给绑定,并且你希望确保你不会导致隐式复制。对于右值引用特定的情况,可以通过删除
func(Binding<C>&& x)
(按照PiotrNycz的示例)来实现。片段:
输出:
错误(
bazel
中的clang-3.9
,当未注解有问题的行时):完整源代码:防止隐式转换.cc
cnjp1d6j7#
好吧,我打算用下面的代码来回答这个问题,但是即使它可以在Visual C中工作,在产生所需的编译错误的意义上,MinGW g 4.7.1接受它,并调用右值引用构造函数!
我想一定是编译器的错误,但我也可能是错的,所以-有人知道吗?
无论如何,下面是代码,它 * 可能 * 会成为一个符合标准的解决方案(或者,它可能会成为我的一个想法!):
xqkwcwgp8#
我首先尝试了PiotrNycz的方法(对于C++03,我被迫在一个项目中使用它),然后我试图找到一个更通用的方法,并提出了这个
ForcedType<T>
模板类。如果我没记错的话,这三种特殊化应该涵盖所有常见用例,我不确定是否真的需要对右值引用进行特殊化(C++11以上),或者按值特殊化就足够了。
如果一个函数有3个参数,而第3个参数不允许隐式转换,则可以这样使用它:
ibps3vxo9#
这里有一个在C++11中使用enable_if的干净简单的解决方案。这个例子使用std::is_same作为 predicate ,但是你可以使用任何其他产生bool的constexpr。