I want to write an abstract Pipeline
class that gets some functions with a specific signature as template parameters and runs them depending on the parse stage for input data. this is the code that I wrote:
#include <array>
enum class ParseState
{
EXTRACTED, /**< EXTRACTED */
IN_PROGRESS, /**< IN_PROGRESS */
REJECTED, /**< REJECTED */
};
struct ParseStage
{
std::size_t stage;
public:
ParseStage() : stage(0)
{}
std::size_t get_stage() const
{
return stage;
}
std::size_t next_stage()
{
return ++stage;
}
void reset()
{
stage = 0;
}
};
template <typename InputDataType>
using ParseResult = std::pair<ParseState, InputDataType>;
template <typename InputDataType, typename ParserState, typename... Args>
using StageFunctionRefType = ParseResult<InputDataType> (&)(const InputDataType &, ParserState &, Args... args);
template <typename InputDataType, typename ParserState, typename... Args,
StageFunctionRefType<InputDataType, ParserState, Args...>... StageFunctions>
class Pipeline
{
static constexpr std::array Stages{ StageFunctions... };
public:
static ParseResult<InputDataType> feed(const InputDataType &input_data, ParserState &parser_state,
ParseStage &parse_stage, Args... args)
{
if (parser_state.parse_state == ParseState::REJECTED)
return { ParseState::REJECTED, input_data };
auto remaining_data = input_data;
while (parse_stage.get_stage() < Stages.size() && remaining_data.size())
{
const auto parse_result = Stages[parse_stage.get_stage()](remaining_data, parser_state, args...);
remaining_data = parse_result.second;
if (parse_result.first == ParseState::EXTRACTED)
parse_stage.next_stage();
else if (parse_result.first == ParseState::REJECTED)
return parse_result;
}
if (parse_stage.get_stage() == Stages.size())
return { ParseState::EXTRACTED, remaining_data };
return { ParseState::IN_PROGRESS, remaining_data };
}
};
but I get an error message: parameter pack 'Args' must be at the end of the template parameter list
How can I fix this? Or do you have any other solutions?
the performance is really important to me so I want to avoid using virtual or std::function
.