所以让我说我有一个像这样的通用函数:
template<typename TFunc>
void templFunc(TFunc func) {
func(3, 6);
}
在编译时是否有任何方法可以验证TFunc的签名,无论它是std :: function还是lambda或任何类型的函数引用。我只想确保TFunc是签名void(int,int)或类似static_assert,所以我可以产生非垃圾错误消息。
答案 0 :(得分:1)
所以我摆弄了一些type_traits的东西,我认为我有一些东西可以验证整个签名,而不仅仅是返回值,并且允许你创建易于读取的static_asserts,而不是签名时没有难以辨认的模板错误不配。这是一个糟糕的解决方案吗?
#include <functional>
template<typename, typename, typename = void>
struct is_signature : std::false_type {};
template<typename TFunc, typename Ret, typename... Args>
struct is_signature<TFunc, Ret(Args...),
typename std::enable_if<
std::is_convertible<
TFunc,
std::function<Ret(Args...)>
>::value
>::type
> : public std::true_type
{};
// works on both functions and lambda's
void blah(int, int) {
}
template<typename TFunc>
void templFunc(TFunc func) {
static_assert(is_signature<TFunc, void(int, int)>::value, "Not gonna work! more info follows:");
func(3, 6);
}
int main() {
auto b = [](int, int) -> void {
};
auto c = [](int) -> void {
};
static_assert(is_signature<decltype(b), void(int, int)>::value, "b convertible to a std::function<void(int, int), so this checks out!");
static_assert(is_signature<decltype(b), void(int)>::value, "b not convertible to a std::function<void(int)>, so this will error in compilation.");
static_assert(is_signature<decltype(blah), void(int, int)>::value, "blah convertible to a std::function<void(int, int), so this checks out!");
static_assert(is_signature<decltype(blah), void(int)>::value, "blah not convertible to a std::function<void(int)>, so this will error in compilation.");
templFunc(b); // <- ok
templFunc(c); // <- static assertion : not gonna work!
return 0;
}
答案 1 :(得分:0)
您可以使用:
template<typename TFunc>
void templFunc(TFunc func) {
static_assert(std::is_void<decltype(func(0,0))>::value,
"Bad template argument. The return type is not void");
func(3, 6);
}
void
。 如果该函数没有采用两个参数,它将在调用func(3,6);
中失败 - 两次。进入static_assert
行,然后进入下一行。
如果int
的参数类型或int
可以提升,转换为或转换为int
的任何其他类型,则函数调用将成功。确保参数类型为#include <type_traits>
template<typename TFunc>
void templFunc(TFunc func) {
static_assert(std::is_void<decltype(func(0,0))>::value, "Bad template argument. The return type is not void");
func(3, 6);
}
void foo()
{
}
void bar(int x, int y)
{
}
int baz(int x, int y)
{
return 0;
}
struct Functor
{
void operator()(long, long)
{
}
};
int main()
{
templFunc(foo); // Not OK. Two few arguments
templFunc(bar); // OK
templFunc(baz); // Not OK. Wrong return type
templFunc([](int, int) -> void {} ); // OK
templFunc(Functor()); // OK
}
只需要一些额外的工作。我不确定那会带来什么。
测试程序:
<com.samsoft.sam.Fab
android:id="@+id/fab"
app:layout_anchor="@id/asd"
app:layout_anchorGravity="top|end"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
答案 2 :(得分:0)
这样的东西使用SFINAE(只有你根据模板参数做出断言;不完全确定原因,我认为这将是最有趣的部分:)):
#include <type_traits>
template<typename TFunc>
typename std::enable_if<std::is_same<typename std::result_of<TFunc(int, int)>::type, void>::value >::type templFunc(TFunc func)
{
func(3, 6);
}
template<typename TFunc>
typename std::enable_if<!std::is_same<typename std::result_of<TFunc(int, int)>::type, void>::value >::type templFunc(TFunc func)
{
static_assert(std::is_same<typename std::result_of<TFunc(int, int)>::type, void>::value, "error; invalid function");
}
auto a = [](int, int) {};
auto b = [](int x, int y) { return x + y; };
int main()
{
templFunc(b);
return 0;
}