显式void指针作为函数参数
Explicit void pointer as function parameter
我有一个函数:
int foo(void * ptr)
{
// ...
}
在C++11/14中,我是否可以在语法上(不带编译器警告等(禁止向void *
本身以外的指针传递?
例如,现在它可以被称为:
foo(new int(42));
我需要禁用它。
我想还有很多其他方法可以做到这一点
使用模板函数很简单(它也适用于C++98(
template <typename X>
int foo (X * ptr);
int foo (void * ptr)
{ return 1; }
int main()
{
int i;
void * vp = &i;
foo(vp); // OK
foo(&i); // linker error
return 0;
}
正如frymode所指出的,前面的解决方案给出的是链接器错误,而不是编译器错误,最好是得到编译器错误。
使用delete
(来自C++11(,我们可以通过使用以下内容来获得编译器错误:
template <typename X>
int foo (X ptr) = delete;
希望这能有所帮助。
您可以使用迂腐的指针习惯用法。您的代码应该如下所示。它利用了这样一个事实,即在更高的间接级别上没有隐式转换:
[现场]
int foo_impl(void * ptr, void **)
{
return 0;
}
template <typename T>
void foo(T* t)
{
foo_impl(t, &t);
}
int main()
{
void* pv;
foo(pv);
//foo(new int(2)); // error: error: invalid conversion from 'int**' to 'void**'
}
如果想要精确的类型匹配,可以使用std::enable_If和std::is_same
#include <iostream>
#include <type_traits>
template <typename T,
typename = typename std::enable_if_t<std::is_same<T, void*>::value>>
int foo(T value)
{
return 5;
}
int main()
{
// return foo(new int(42)); // error: no matching function for call to 'foo(int*)'
return foo((void*)(new int(42)));
}
您可以将函数转换为模板函数,然后使用type_traits
:中的static_assert
和std::is_void
template<typename T>
int foo(T *ptr) {
static_assert(std::is_void<T>::value, "!");
// ....
}
否则,您可以在返回类型上使用std::enable_if_t
:
template<typename T>
std::enable_if_t<std::is_void<T>::value, int>
foo(T *ptr) {
// ....
return 0;
}
等等,其他用户已经提出了其他有趣的解决方案,并给出了他们的答案。
下面是一个最小的工作示例:
#include<type_traits>
template<typename T>
int foo(T *ptr) {
static_assert(std::is_void<T>::value, "!");
// ....
return 0;
}
int main() {
int i = 42;
void *p = &i;
foo(p);
// foo(&i); // compile error
}
惯用方法是创建一个新类型来表示void*
,以避免您所描述的问题。许多优秀C++实践的倡导者建议创建类型,以避免对应该传入的内容产生任何疑问,也避免编译器允许您这样做。
class MyVoid
{
//... implement in a way that makes your life easy to do whatever you are trying to do with your void* stuff
};
int foo(MyVoid ptr)
{
// ...
}
您不需要C++11来确保编译时出错:
template<class> struct check_void;
template<> struct check_void<void> { typedef void type; };
template<class T> typename check_void<T>::type *foo(T *ptr) { return ptr; }
int main()
{
foo(static_cast<void *>(0)); // success
foo(static_cast<int *>(0)); // failure
}
相关文章:
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 当从函数参数中的临时值调用复制构造函数时
- 如何从"decltype()"获取函数参数的数量<funtion>?
- 如何将lambda作为模板类的成员函数参数
- 模板参数推导失败,函数参数/参数不匹配
- 如何在C++中将迭代器作为函数参数传递
- 将函数参数"const char*"转换为"std::string_view"是
- C++ 如何将数组值解压缩为函数参数
- 主函数参数的属性
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- "Warning: Comma within array index expression"但逗号分隔函数参数
- 如何定义在用作函数参数时工作的类模板的转换
- 将函数参数完美转发到函数指针:按值传递呢?
- 为什么我不能将引用作为 std::async 的函数参数传递
- 什么..(省略号)作为函数原型中唯一的函数参数,C++?
- 是否可以就地构造一个固定大小的数组作为函数参数?
- 接受模板作为函数参数
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- Arduino 函数参数