C++ - 为什么 std::function<some_type_t, void> 无效?
C++ - Why is std::function<some_type_t, void> invalid?
在 C++ 中,如果我尝试这样做:
std::function<void(bool,void)>
然后编译器会抛出错误。为什么是这样?它在许多情况下很有用。一个例子:
//g++ -std=c++17 prblm.cpp
#include <cstdio>
#include <functional>
template<class type_t>
class some_callback
{
public:
using callback_t = std::function<void(bool,type_t)>;
some_callback(callback_t _myfunc)
{
this->myfunc = _myfunc;
}
callback_t myfunc;
};
using callback_with_just_bool = some_callback<void>;
using callback_with_an_int_too = some_callback<int>;
int main()
{
auto my_callback_with_int = callback_with_an_int_too([](bool x, int y)
{
}); //OK
auto my_callback_just_bool = callback_with_just_bool([](bool x)
{
}); //Error
auto my_callback_just_bool = callback_with_just_bool([](bool x,void z)
{
}); //Error
return 0;
}
如果用户希望在他们的回调中有选择地包含额外的数据,但不是必须的,这允许一个非常干净的语法。但是,编译器将拒绝尝试初始化 callback_with_just_bool
对象的代码
为什么会这样,是否有解决方法?谢谢。
编辑:在现实世界的代码中,我尝试这样做的具体原因是在事件系统中。向事件系统提供了有关希望 有条件地 接收事件 (e.x. "if you're close enough to the source, you'll receive a sound event") 的单个对象的数据,以及向回调提供的数据 关于事件(e.x。"a 10khz noise at X200 Y200")。大多数时候,检查需求所需的数据将存在于提供给事件回调 about 的数据中,但如果不是,我想提供一个可选的附加数据结构案件。因此,如果用户不需要这个额外的数据结构,他们会指定 "void"。
问题不在于您显示的代码,这是因为在 C/C++ 中,您无法将函数 f 定义为
void f(bool b, void v) {}
原因是,正如@Peter Ruderman 所说,void
不是有效的参数类型。
您可以创建专业化:
template<class type_t>
class some_callback
{
std::function<void(bool,type_t)> myfunc;
};
template<>
class some_callback<void>
{
std::function<void(bool)> myfunc;
};
可变参数模板是一种方法:
template <class... T>
struct some_callback
{
std::function<void(bool, T...)> myfunc;
};
using callback_with_just_bool = some_callback<>;
using callback_with_an_int_too = some_callback<int>;
使用别名模板更简洁:
template <class... T> using callback_type = std::function<void(bool, T...)>;
int main()
{
callback_type<int> my_callback_with_int = [](bool x, int y)
{
}; //OK
callback_type<> my_callback_just_bool = [](bool x)
{
}; //OK now too...
}
“这是为什么?”
因为 void
在参数列表中唯一允许的用法是表明该函数不接受任何参数。
来自 [function]:
void
Indicates that the function takes no parameters, it is the exact synonym for an empty parameter list: int f(void);
and int f();
declare the same function. Note that the type void (possibly cv-qualified) cannot be used in a parameter list otherwise: int f(void, int);
and int f(const void);
are errors (although derived types, such as void*
can be used)
“有解决办法吗?”
我建议专攻 void
:
template<class type_t>
class some_callback
{
std::function<void(bool,type_t)> myfunc;
};
template<>
class some_callback<void>
{
std::function<void(bool)> myfunc;
};
其他答案已经解释了原因。这回答了 "is there a clean way around it?"
我通常为回调做的是使用 lambdas。
std::function<void(void)> myfunc;
bool b = false;
int i = 42;
myfunc = [&]() { if (b) ++i; };
有人建议将 "regular void" 添加到语言中。
其中,void 成为所有其他类型隐式转换为的单态类型。
你可以用
来模拟这个
struct monostate_t {
template<class T>
monostate_t(T&&) {}
};
然后
using callback_with_just_bool = some_callback<monostate_t>;
auto my_callback_just_bool = callback_with_just_bool([](bool x, auto&&...)
{
});
大致按照你喜欢的方式工作。
在 C++ 中,如果我尝试这样做:
std::function<void(bool,void)>
然后编译器会抛出错误。为什么是这样?它在许多情况下很有用。一个例子:
//g++ -std=c++17 prblm.cpp
#include <cstdio>
#include <functional>
template<class type_t>
class some_callback
{
public:
using callback_t = std::function<void(bool,type_t)>;
some_callback(callback_t _myfunc)
{
this->myfunc = _myfunc;
}
callback_t myfunc;
};
using callback_with_just_bool = some_callback<void>;
using callback_with_an_int_too = some_callback<int>;
int main()
{
auto my_callback_with_int = callback_with_an_int_too([](bool x, int y)
{
}); //OK
auto my_callback_just_bool = callback_with_just_bool([](bool x)
{
}); //Error
auto my_callback_just_bool = callback_with_just_bool([](bool x,void z)
{
}); //Error
return 0;
}
如果用户希望在他们的回调中有选择地包含额外的数据,但不是必须的,这允许一个非常干净的语法。但是,编译器将拒绝尝试初始化 callback_with_just_bool
为什么会这样,是否有解决方法?谢谢。
编辑:在现实世界的代码中,我尝试这样做的具体原因是在事件系统中。向事件系统提供了有关希望 有条件地 接收事件 (e.x. "if you're close enough to the source, you'll receive a sound event") 的单个对象的数据,以及向回调提供的数据 关于事件(e.x。"a 10khz noise at X200 Y200")。大多数时候,检查需求所需的数据将存在于提供给事件回调 about 的数据中,但如果不是,我想提供一个可选的附加数据结构案件。因此,如果用户不需要这个额外的数据结构,他们会指定 "void"。
问题不在于您显示的代码,这是因为在 C/C++ 中,您无法将函数 f 定义为
void f(bool b, void v) {}
原因是,正如@Peter Ruderman 所说,void
不是有效的参数类型。
您可以创建专业化:
template<class type_t>
class some_callback
{
std::function<void(bool,type_t)> myfunc;
};
template<>
class some_callback<void>
{
std::function<void(bool)> myfunc;
};
可变参数模板是一种方法:
template <class... T>
struct some_callback
{
std::function<void(bool, T...)> myfunc;
};
using callback_with_just_bool = some_callback<>;
using callback_with_an_int_too = some_callback<int>;
使用别名模板更简洁:
template <class... T> using callback_type = std::function<void(bool, T...)>;
int main()
{
callback_type<int> my_callback_with_int = [](bool x, int y)
{
}; //OK
callback_type<> my_callback_just_bool = [](bool x)
{
}; //OK now too...
}
“这是为什么?”
因为 void
在参数列表中唯一允许的用法是表明该函数不接受任何参数。
来自 [function]:
void
Indicates that the function takes no parameters, it is the exact synonym for an empty parameter list:
int f(void);
andint f();
declare the same function. Note that the type void (possibly cv-qualified) cannot be used in a parameter list otherwise:int f(void, int);
andint f(const void);
are errors (although derived types, such asvoid*
can be used)
“有解决办法吗?”
我建议专攻 void
:
template<class type_t>
class some_callback
{
std::function<void(bool,type_t)> myfunc;
};
template<>
class some_callback<void>
{
std::function<void(bool)> myfunc;
};
其他答案已经解释了原因。这回答了 "is there a clean way around it?"
我通常为回调做的是使用 lambdas。
std::function<void(void)> myfunc;
bool b = false;
int i = 42;
myfunc = [&]() { if (b) ++i; };
有人建议将 "regular void" 添加到语言中。
其中,void 成为所有其他类型隐式转换为的单态类型。
你可以用
来模拟这个struct monostate_t {
template<class T>
monostate_t(T&&) {}
};
然后
using callback_with_just_bool = some_callback<monostate_t>;
auto my_callback_just_bool = callback_with_just_bool([](bool x, auto&&...)
{
});
大致按照你喜欢的方式工作。