0
저는 명령 행 인터프리터를 작성하고 있습니다. 예전의 C++ 03 일에서는 고정 프로토 타입을 선언하고 그 안에 인수를 구문 분석해야했습니다. 그러나 C++ 11에서는 가변적 인 템플릿을 가지고 있으므로 어떤 함수 원형에서도 작동 할 코드를 작성하고 std :: stringstream을 사용하여 모든 인수를 자동으로 구문 분석합니다.std :: vector의 std :: strings를 임의의 형식의 std :: tuple로 구문 분석합니다.
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <tuple>
#include <functional>
template <typename... Args>
class Command
{
public:
Command(std::function<void(Args...)> callback, std::tuple<Args...> args)
: callback(callback), args(args)
{
}
void Execute(std::vector<std::string> call)
{
Parse(std::integral_constant<std::size_t, std::tuple_size<decltype(args)>::value - 1>{}, args, call);
CallFunc(GenerateArgumentIndexPack<std::tuple_size<decltype(args)>::value>::Pack());
}
private:
std::function<void(Args...)> callback;
std::tuple<Args...> args;
template <typename T>
void Fill(const std::string& input, T& 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(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(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>
void CallFunc(ArgumentIndexPack<ArgumentIndexes...>)
{
callback(std::get<ArgumentIndexes>(args)...);
}
};
void Foo(int a, float b)
{
std::cout << a << ' ' << b;
}
int main(int argc, char* argv[])
{
try
{
Command<int, float> cmd1(&Foo, std::make_tuple(1, 2.0f));
cmd1.Execute({"3", "4.0"});
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what();
}
catch (...)
{
std::cerr << "Unknown exception.";
}
}
컴파일 오류는 다음과 같습니다 :
/home/fatony/Stuff/C++/Test/Src/Main.cpp: In instantiation of ‘void Command<Args>::Execute(std::vector<std::basic_string<char> >) [with Args = {int, float}]’:
/home/fatony/Stuff/C++/Test/Src/Main.cpp:96:18: required from here
/home/fatony/Stuff/C++/Test/Src/Main.cpp:34:84: error: dependent-name ‘Command<Args>::GenerateArgumentIndexPack<std::tuple_size<decltype (((Command<Args>*)this)->Command<Args>::args)>::value>::Pack’ is parsed as a non-type, but instantiation yields a type
CallFunc(GenerateArgumentIndexPack<std::tuple_size<decltype(args)>::value>::Pack());
^
/home/fatony/Stuff/C++/Test/Src/Main.cpp:34:84: note: say ‘typename Command<Args>::GenerateArgumentIndexPack<std::tuple_size<decltype (((Command<Args>*)this)->Command<Args>::args)>::value>::Pack’ if a type is meant
컴파일 타임에 유형을 모르는 경우 정적 유형을 지정할 수 없습니다. –
유형을 알고 있고 설계에 동적 연결이 없습니다. – Lyberta
#을 #include해야합니까? –
Pete