2014-05-23 2 views
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 
+0

컴파일 타임에 유형을 모르는 경우 정적 유형을 지정할 수 없습니다. –

+0

유형을 알고 있고 설계에 동적 연결이 없습니다. – Lyberta

+0

# 을 #include해야합니까? – Pete

답변

2

코드에서 두 가지 문제가 있습니다

지금까지, 나는 다음과 같은 코드를 얻었다. 먼저 : #include <sstream>이어야합니다.

둘째 : 그러한 색인이 없기 때문에 std::get<std::tuple_size<...>>(tuple)의 호출이 올바르지 않습니다. 당신은,이 함수는 컴파일러 오류에 명시된 바와 같이

CallFunc(typename 
GenerateArgumentIndexPack<std::tuple_size<decltype(args)>::value>::Pack()); 

해야 CallFunc에서 두 번째 오류에 대한이

void Execute(std::vector<std::string> call) 
{ 
    //auto size = call.size(); 
    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()); 
} 

를 사용하여 문제를 해결할 수 있습니다.

관련 문제