我的问题如下。我想在包装器中调用任何自由函数,我想在包装器中自动传递它。
这个想法是通过GetArgument<float>()
之类的函数调用传递参数。最终,我想从虚拟机中获取值,并将它们传递给我绑定的函数。我需要将正确类型的正确GetArgument<T>
放在函数调用中的正确位置。
这是我尝试的最小工作示例。主:
#include "FunctionWrapper.h"
#include <iostream>
void say( int val ) {
std::cout << "called with " << val << std::endl;
}
int main() {
InvokeWithArguments( say );
return 0;
}
这就是魔术发生的地方。我在源代码末尾遇到编译器错误:
#pragma once
#include <cstdlib>
#include <cstdint>
#include <tuple>
#include <type_traits>
/*
* FUNCTION TRAITS
*/
template< typename F >
struct FunctionTraits;
template< typename R, typename... Args >
struct FunctionTraits< R( Args... ) > {
using ReturnType = R;
constexpr static const uint32_t arity = sizeof...( Args );
template< std::size_t N >
struct Argument {
static_assert( N < arity, "FunctionTraits error: invalid argument count parameter" );
using type = typename std::tuple_element< N, std::tuple< Args... > >::type;
};
};
/*
* ARGUMENT GETTER (for demonstration)
**/
template< typename T >
T GetArgument() {}
template<>
float GetArgument() {
return 3.3f;
}
template<>
int GetArgument() {
return 5;
}
/*
* AUTOMATIC INVOCATION
**/
template< typename Function, std::size_t... index >
decltype( auto ) InvokeHelper( Function&& f, std::index_sequence<index...> ) {
using Traits = FunctionTraits< decltype(f) >;
// COMPILER FAILS HERE, EXPECTS ) BEFORE :: TOKEN
return f( GetArgument< Traits::Argument<index>::type >()... );
}
template< typename Function >
decltype( auto ) InvokeWithArguments( Function&& f ) {
constexpr auto Arity = FunctionTraits< decltype(f) >::arity;
return InvokeHelper( std::forward<Function>( f ), std::make_index_sequence<Arity>{} );
}
我不明白为什么return f( GetArgument< Traits::Argument<index>::type >()... );
失败了。据我所知,Traits::Argument<index>::type
是一个类型,所以我不知道为什么编译器会期望在它中间关闭函数调用。
最后,一个小小的理智检查,因为我是这样的模板编程菜鸟。我希望在函数调用的括号之间有一个逗号分隔的GetArgument<T>
调用列表。这甚至是我的代码在做什么?
答案 0 :(得分:4)
您应该使用:
return f( GetArgument< typename Traits::template Argument<index>::type >()... );
// ^^^^^^^^ ^^^^^^^^^
在此之后,编译器会抱怨您的FunctionTraits<void(&)(int)>
无法实例化,可以通过std::remove_reference
删除函数类型中的引用来解决此问题。
这是因为void(int)
与void(&)(int)
不同而void(*)(int)
不同。第一个是函数类型,第二个是函数引用类型,后者是函数指针类型。
所有这些都将产生:
template< typename Function, std::size_t... index >
decltype( auto ) InvokeHelper( Function&& f, std::index_sequence<index...> ) {
using Traits = FunctionTraits< typename std::remove_reference<decltype(f)>::type >;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^
return f( GetArgument< typename Traits::template Argument<index>::type >()... );
// ^^^^^^^^ ^^^^^^^^^
}
template< typename Function >
decltype( auto ) InvokeWithArguments( Function&& f ) {
constexpr auto Arity = FunctionTraits< typename std::remove_reference<decltype(f)>::type >::arity;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^
return InvokeHelper( std::forward<Function>( f ), std::make_index_sequence<Arity>{} );
}