在C++中使用"void"模板参数
Using 'void' template arguments in C++
举以下最小的例子:
using Type1 = std::function<void(void)>;
template <typename T>
using Type2 = std::function<void(T)>;
Type1 whyDoesThisWork;
Type2<void> andYetThisDoesNot;
如果是第二个类型别名,我会收到错误"参数可能没有'void'类型"。(我用Xcode 4.5,Clang/c ++ 11/libc ++,OS X 10.7进行了测试。
我觉得这很奇怪:我本来希望Type1
和Type2<void>
的行为相同。这是怎么回事?有没有办法重写第二个类型别名,以便我可以编写Type2<void>
并获得std::function<void(void)>
而不是错误?
编辑 我可能应该补充一点,我想要这样做的原因是允许如下:
template <typename ... T>
using Continuation = std::function<void(T...)>;
auto someFunc = []() -> void {
printf("I'm returning void!n");
};
Continuation<decltype(someFunc())> c;
Continuation<decltype(someFunc())>
变得Continuation<void>
,我得到错误。
简短的回答是"模板不是字符串替换"。 void f(void)
只有在它是C++中void f()
的别名时才有意义,以便向后兼容 C。
第一步是使用可变数,如其他地方所述。
第二步是弄清楚如何将void
返回函数映射到...好吧,也许像std::function<void()>
这样的东西,或者别的什么。 我说也许是别的,因为与其他情况不同,你不能称之为std::function<void()> foo; foo( []()->void {} );
——这不是一个真正的延续。
像这样的东西可能是:
template<typename T>
struct Continuation
{
typedef std::function<void(T)> type;
};
template<>
struct Continuation<void>
{
typedef std::function<void()> type;
};
然后像这样使用它:
auto someFunc = []()->void {};
Continuation<decltype(someFunc())>::type c;
这给了你想要的类型。 您甚至可以添加适用于延续:
template<typename T>
struct Continuation
{
typedef std::function<void(T)> type;
template<typename func, typename... Args>
static void Apply( type const& cont, func&& f, Args... args)
{
cont( f(args...) );
}
};
template<>
struct Continuation<void>
{
typedef std::function<void()> type;
template<typename func, typename... Args>
static void Apply( type const& cont, func&& f, Args... args)
{
f(args...);
cont();
}
};
这允许您在传入类型为 void 或非 void 类型时将延续统一应用于函数的执行。
但是,我会问"你为什么要这样做"?
我没有实际的答案,只有我在评论中所说的: 您不能将void
作为函数类型,例如:
int foo(int, char, void, bool, void, void); // nonsense!
我相信 T(void)
只允许作为 C 的兼容性符号(它区分声明和原型,与 C++ 非常不同,并且需要能够说"没有参数")。
因此,解决方案应该是可变的:
template <typename ...Args> using myType = std::function<void(Args...)>;
这样你就可以正确地没有参数:
myType<> f = []() { std::cout << "Boon"; }
有几个答案已经解释了基本原理。 为了补充这些答案,规范说(C++11 §8.3.5[dcl.func]/4):
由非依赖类型
void
的单个未命名参数组成的参数列表为 等效于空参数列表。除此特殊情况外,参数不得具有 cvvoid
类型。
在Type2
示例中,void(T)
中的T
是依赖类型,它取决于模板参数。
当一个函数被声明为接受一个类型为 void
的参数时,就像在 std::function<void(void)>
中一样,这实际上只是一种愚蠢的说法,它接受零参数。但是您声明 Type2 的方式是作为具有不返回任何内容 (void) 的签名的std::function
,但它需要 1 个参数。 void 不是可以用作参数的类型,它只是声明没有参数的一种方式。 因此,它不适用于 Type2,因为这需要一个可以用作参数的实际类型。
void 传递给函数,则可以将其解释为空参数。毕竟你没有使用空指针,所以
void func (void)
成为
void func ()
- 在派生函数中指定void*参数
- void 函数可以传递值参数吗?
- 如何在C++中使用 Void 而不会收到有关参数的错误
- std::function<void()> 接受参数
- C++ 类型的参数与 void (__cdecl*)(void) 类型的参数不兼容,当调用 std::atexit()
- 是否将invoke_result与void参数类型一起使用
- 组合模板参数形成函数签名时无效的 void 参数
- 使用void* 参数定义纯虚函数的抽象基类.派生类匹配参数是指向某种类型的指针
- 为什么 void 参数不能存在于具有多个参数的函数中?
- Pthreads将void*参数强制转换为int数组
- C 函数声明对类型"void(*fcn)(void*)"参数的说明
- 从模拟函数调用中捕获 void* 参数
- 为void参数指定一个模板
- 如何在c++ OCX模块中指定一个接受void*参数的函数
- 某些 GL 函数的好奇"void*"参数
- 如何在C++中为多个对象类型使用void*参数
- 如何使void*参数在函数中保存其局部结果,该函数使用struct *调用
- 在需要void*参数的函数中传递unique_ptr最安全的方法是什么?
- 如何在类/函数模板中传递void参数
- 没有参数和C++中的void参数有什么区别