我的函数使用一组给定的输入参数(variadic)调用Python函数,并返回一个包含函数输出的元组(可变参数,因为输出因调用的函数而异)。
我正在使用C ++ 11通过MinGW-w64编译器的g ++端口在Windows 10机器上进行编译。我已经按如下方式声明了这个模板化的可变参数函数(并调用它):
// Declaration (in PyInterface.h)
template <typename... Inputs, typename... Outputs>
const std::tuple<Outputs...>& callFunction(const std::string &modulePath, const std::string &funcName, Inputs&&... args) {
// Calls a Python function & packs output variables into a std::tuple...
}
// Sample call (in main.cpp)
const std::tuple<std::string, std::string> output = pi.callFunction(myModulePath, myFuncName, inputArg1, inputArg2, inputArg3);
但是,抛出此错误(为了便于阅读,请使用...
缩短):
conversion from 'const std::tuple<>' to non-scalar type 'const std::tuple<std::__cxx11::basic_string<...>, std::__cxx11::basic_string<...> >' requested
据我所知using two variadic templates is legal。另外,在我看来,返回类型是由变量(const std::tuple<std::string, std::string> output
)显式设置的我试图将函数的结果赋给,所以编译器应该知道所需的返回值
类型是。
最初,我认为错误只是表明我没有适当地使用可变参数模板。我尝试使用嵌套模板参数(图示为here)来指定返回类型(即const T<Outputs...>& callFunction
)。但是,这只会成功生成一条错误消息,指出T
的模板扣除失败。
此错误表明我的直觉是错误的,并且在我的原始函数中,编译器不会从output
类型中推断出所需的返回类型。
为什么我的直觉错了?如何正确使用可变参数模板来指定此函数的返回类型?
答案 0 :(得分:1)
如果要根据函数范围内返回的对象的类型推断返回类型,如果您使用的是C ++ 14,则可以使用auto
作为返回类型。它就像一个魅力
template <typename... Inputs>
const auto& callFunction(
const std::string &modulePath,
const std::string &funcName,
Inputs&&... args) {
return object;
}
始终要注意您从此函数返回const引用。
如果您使用的是C ++ 11,则可以使用尾随返回类型,例如
template <typename T>
auto identity_return(T& obj) -> decltype(obj) {
return obj;
}
其中decltype(obj)
是您要返回的事物的类型。在这种情况下再次提防它再次作为参考。
通常虽然尝试并返回函数中的值,但如果您不确定返回的内容将比返回值更长,则返回引用可能会导致悬空引用。
另一种解决方案是手动指定Outputs...
类型列表,让编译器推导出类型Inputs...
template <typename... Outputs, typename... Inputs>
const std::tuple<Outputs...>& callFunction(
const std::string &modulePath,
const std::string &funcName,
Inputs&&... args) { ... }
auto tup = callFunction<std::string, std::string>(modulePath, funcName, args);
答案 1 :(得分:0)
与C ++编译器错误消息一样,第一个是您需要查看的唯一消息。我猜测(因为你没有提供代码)你正在创建一个tuple
值,然后返回一个const引用。在函数结束时,tuple
被销毁,那么引用应该引用什么?您应该返回tuple<Outputs...>
。
我认为您可以通过交换Input
和Output
类型包来实现您的目标。此代码还说明了使用Inputs
函数迭代show
类型包。您可以执行类似的操作,从Python元组对象和tuple<Outputs...>
类型包中构建Outputs
值。
#include <iostream>
#include <tuple>
#include <utility>
using namespace std;
template< typename Output > struct convert_t;
template<> struct convert_t< string >
{
string operator()( const char *text ) const
{
return text;
}
string operator()( double val ) const
{
return to_string( val );
}
};
inline void show()
{}
template< typename First, typename... Others >
inline void show( First &&first, Others&&... others )
{
cout << first << "\n";
show( forward< Others >( others )... );
}
template< typename... Outputs, typename... Inputs >
inline tuple< Outputs... > funkyfunc( Inputs&&... inputs )
{
cout << "Inputs...\n";
show( forward< Inputs >( inputs )... );
return tuple< Outputs... >( convert_t< Outputs >()( inputs )... );
}
int main()
{
auto t = funkyfunc< string, string >( "text", 123.0 );
cout << "Outputs...\n";
cout << get<0>( t ) << "\n";
cout << get<1>( t ) << "\n";
return 0;
}