C ++可变参数模板返回类型

时间:2017-06-29 17:25:45

标签: c++ variadic-templates return-type

我的函数使用一组给定的输入参数(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类型中推断出所需的返回类型。

为什么我的直觉错了?如何正确使用可变参数模板来指定此函数的返回类型?

2 个答案:

答案 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...>

我认为您可以通过交换InputOutput类型包来实现您的目标。此代码还说明了使用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;
}