我有一个功能:
AE
我可以在C ++ 11/14中语法上(不使用编译器警告等)禁用传递除int foo(void * ptr)
{
// ...
}
以外的指针吗?
例如,现在它可以被称为:
void *
我需要禁用它。
答案 0 :(得分:18)
我想还有很多其他方法可以做到。
使用模板函数很简单(它也适用于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;
希望这有帮助。
答案 1 :(得分:9)
如果您想要完全匹配类型,可以将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)));
}
答案 2 :(得分:9)
您可以使用pedantic pointer idiom。你的代码看起来应该如下。它利用了这样一个事实:在一个间接层的较高层没有隐式转换:
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**'
}
答案 3 :(得分:7)
您可以将该功能转为模板1,然后使用static_assert
中的std::is_void
和type_traits
:
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
}
答案 4 :(得分:5)
惯用的方法是创建一个新类型来表示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)
{
// ...
}
答案 5 :(得分:1)
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
}