C++ variadic模板返回类型
我的函数使用一组给定的输入参数(variadic)调用一个Python函数,并返回一个包含该函数输出的变量(可变参数,因为输出因函数调用而变化)。C++ variadic模板返回类型
我正在使用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
的类型推导出所需的返回类型。
为什么我的直觉错了?如何正确使用可变参数模板来指定此函数的返回类型?
如果您想根据函数范围内返回的对象的类型来推导返回类型,如果您使用的是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);
您正在返回对已销毁的本地对象的引用。 – NathanOliver
@NathanOliver这就是为什么我最后提到“提防”的原因! – Curious
我猜想我想要沟通的是为什么在你的例子中使用错误的代码时,你可以“正确的方式”做到这一点,并向OP解释你为什么这样做。 – NathanOliver
照例与C++编译器的错误消息,第一个是你需要的只有一个看看。我猜(因为你没有提供代码),你正在创建一个tuple
值,然后返回一个const引用。在该函数结束时,tuple
被破坏,因此参考文献应引用什么内容?您应该只返回tuple<Outputs...>
。
我认为你可以通过交换Input
和Output
类型包来实现你想要的。此代码还说明了使用show
函数对Inputs
型包进行迭代。您可以执行类似的操作,以从Python元组对象和Outputs
类型包构建tuple<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;
}
你从不指定'Outputs'的类型,所以没有。 – NathanOliver
@NathanOliver您能否详细说明我如何为'Outputs'指定类型?我已经尝试将我的调用修改为'pi.callFunction <:string>',但我无法弄清楚错误消息的含义:'error:can not bind'const string {aka const std :: __ cxx11 :: basic_string}'左值to'std :: __ cxx11 :: basic_string &&' –
您明确指定'string'为输入类型。你得到一个右值引用,并与函数参数声明'Inputs &&'结合。你正在传递一个'const string'的左值,在使用它之前至少需要删除'const'。除了我给出的输入类型隐式提取的答案之外,您可以显式指定'const string&'为Input类型,当与Inputs &&组合时,它仍然是'const string&'。 –