gpt4 book ai didi

c++ - 如何使用模板将变量传递给具有任何签名的函数?

转载 作者:行者123 更新时间:2023-11-30 01:47:00 24 4
gpt4 key购买 nike

我的问题如下。我想在包装器内调用任何自由函数,并且我想在包装器内自动将参数传递给它。

想法是通过像GetArgument<float>() 这样的函数调用来传递参数。 .最终我想从虚拟机中获取值,并将它们传递给我正在绑定(bind)的函数。我需要放置正确的 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>在函数调用的括号之间。这就是我的代码所做的吗?

最佳答案

你应该使用:

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>{} );
}

Live demo

关于c++ - 如何使用模板将变量传递给具有任何签名的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32296961/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com