gpt4 book ai didi

c++ - void 麻烦将值返回到字符串

转载 作者:行者123 更新时间:2023-11-30 05:30:38 25 4
gpt4 key购买 nike

基于这篇文章,我尝试创建一个通用解析器,它将被调用函数的返回值输出为字符串。

Parsing std::vector of std::strings into std::tuple of arbitrary types

不幸的是,我没有弄清楚,如何格式化返回 void 的函数的返回值...

template<class R, class T, class... Args> class CCmd {
public:
CCmd(R (T::* fptr)(Args...), T * obj){}

auto call(Args&&... args) -> R {

auto func = std::mem_fun(mFunction);

return func(mObject, std::forward<Args>(args)...);
}

protected:

R (T::* mFunction)(Args...);

T * mObject;
};

和:

template< class R, class T, class... Args> class CCommand : public CCmd<R,T,Args...> {

public:
CCommand(R (T::* fptr)(Args...), T * obj) :
CCmd<R,T,Args...>(fptr, obj) {
}

void Execute(std::vector<std::string> && parameters, std::string & returnValue) {
if(parameters.size() >= std::tuple_size<decltype(args)>::value) {

std::stringstream stream;

Parse(std::integral_constant<std::size_t, std::tuple_size<decltype(args)>::value - 1>{}, std::forward<decltype(args)>(args), std::forward<std::vector<std::string>>(parameters));

/* the following line fails, if R is of type void */
stream << CallFunc(typename GenerateArgumentIndexPack<std::tuple_size<decltype(args)>::value>::Pack());

stream >> returnValue;

} else {
returnValue = "not enough parameters";
}
}




protected:

std::tuple<Args...> args;

template <typename X, typename Y>
void Fill(const Y && input, X & output) {
std::stringstream stream;
stream << input;
stream >> output;
}

template<std::size_t N, typename... Ts>
void Parse(std::integral_constant<std::size_t, N>, std::tuple<Ts...>&& info, std::vector<std::string>&& tokens) {
Fill(std::forward<std::string>(tokens[N]), std::get<N>(info));
Parse(std::integral_constant<std::size_t, N - 1>{}, info, tokens);
}

template<typename... Ts>
void Parse(std::integral_constant<std::size_t, 0>, std::tuple<Ts...>&& info, std::vector<std::string>&& tokens) {
Fill(std::forward<std::string>(tokens[0]), std::get<0>(info));
}

template <std::size_t... ArgumentIndexes>
struct ArgumentIndexPack {};

template <std::size_t NumberOfArgumentIndexesToGenerate, std::size_t... GeneratedArgumentIndexes>
struct GenerateArgumentIndexPack : GenerateArgumentIndexPack<NumberOfArgumentIndexesToGenerate - 1, NumberOfArgumentIndexesToGenerate - 1, GeneratedArgumentIndexes...> {};

template <std::size_t... GeneratedArgumentIndexes>
struct GenerateArgumentIndexPack<0, GeneratedArgumentIndexes...> {
using Pack = ArgumentIndexPack<GeneratedArgumentIndexes...>;
};

template <std::size_t... ArgumentIndexes>
auto CallFunc(ArgumentIndexPack<ArgumentIndexes...>) -> R {
return CCmd<R,T,Args...>::call(std::forward<Args>(std::get<ArgumentIndexes>(args))...);
}
};

类:

class CMyClass {
public:
void voidFunc() {
std::cout << "CMyClass::voidFunc" << std::endl;
}

void voidDoubleFunc(double d) {
std::cout << "CMyClass::voidDoubleFunc(" << d << ")" << std::endl;
}
};

主要内容:

int main(int argc, char** argv) {

CMyClass oMyClass;
CCommand<void, CMyClass> testObj0(&CMyClass::voidFunc, &oMyClass);
CCommand<void, CMyClass, double> testObj3(&CMyClass::voidDoubleFunc, &oMyClass);

std::string retval;

// This fails as get on a tuple with 0 elements seems to be invalid
testObj0.Execute({}, retval);
// This doesn't compile, as the voidDoubleFunc returns void
testObj3.Execute({"1.23", retval);

return 0;
}

编译器调用:

g++ -c src/main.cpp -o src/main.o -std=c++11

在 R 不是 void 类型的 R T::f() 上调用 Execute 时的错误消息 (1):

src/main.cpp: In instantiation of 'void CCommand<R, T, Args>::Parse(std::integral_constant<long long unsigned int, N>, std::tuple<_Args2 ...>&&, std::vector<std::basic_string<char> >&&) [with long long unsigned int N = 18446744073709551615ull; Ts = {}; R = void; T = CMyClass; Args = {}]':
src/main.cpp:73:179: required from 'void CCommand<R, T, Args>::Execute(std::vector<std::basic_string<char> >&&, std::string&) [with R = void; T = CMyClass; Args = {}; std::string = std::basic_string<char>]'
src/main.cpp:147:31: required from here
src/main.cpp:98:68: error: no matching function for call to 'get(std::tuple<>&)'
Fill(std::forward<std::string>(tokens[N]), std::get<N>(info));

在 Args... 为非 void 的 void T::f(Args...) 上调用 Execute 时出现错误消息 (2):

src/main.cpp: In instantiation of 'void CCommand<R, T, Args>::Execute(std::vector<std::basic_string<char> >&&, std::string&) [with R = void; T = CMyClass; Args = {double}; std::string = std::basic_string<char>]':
src/main.cpp:156:43: required from here
src/main.cpp:76:11: error: no match for 'operator<<' (operand types are 'std::stringstream {aka std::basic_stringstream<char>}' and 'void')
stream << CallFunc(typename GenerateArgumentIndexPack<std::tuple_size<decltype(args)>::value>::Pack());

最佳答案

对于您的第一个问题,您只需为 Parse 创建和重载:

void Parse(std::integral_constant<std::size_t, -1>, 
std::tuple<>&& info, std::vector<std::string>&& tokens) {
}

对于第二个问题(返回 void 的方法),您可以使用中间 struct 作为结果,并为 专门化 CCmd无效:

中间结构ReturnOf:

template <typename R>
struct ReturnOf {
typedef R return_type;
};

template <>
struct ReturnOf<void> {
typedef std::string return_type;
};

针对 voidCCmd 特化:

template<class T, class... Args> class CCmd<void, T, Args...> {
public:
CCmd(void (T::* fptr)(Args...), T * obj) : mFunction(fptr), mObject(obj) { }

auto call(Args&&... args) -> std::string {
auto func = std::mem_fun(mFunction);
func(mObject, std::forward<Args>(args)...);
return std::string();
}

protected:
void (T::* mFunction)(Args...);
T * mObject;
};

最后在 CCommand 中:

template <std::size_t... ArgumentIndexes>
auto CallFunc(ArgumentIndexPack<ArgumentIndexes...>)
-> typename ReturnOf<R>::return_type {
...
}

关于c++ - void 麻烦将值返回到字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35895557/

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