Skip to main content
added 281 characters in body
Source Link
Loki Astari
  • 97.7k
  • 5
  • 126
  • 341

So here's what I'm hoping to find out: Is this code idiomatic modern C++?

Pretty much.
You use recursion to handle the multiple arguments. But a better technique may be to use the compiler to build objects to handle each argument. Unfortunately the way you have to defined the interface makes this a bit hard. If we re-consider the interface to make it like C-scanf.

template<typename T>
int parser(char const*& format, char const*& value, T& value)
{
     // Parse format and value.
     // convert the first % in format into value and save in value.
     // return 1 if value was correctly parsed otherwise 0
}

template<typename... Args)
int tscanf(char const* format, char const&const* value, Args&... args)
{
    // This will call parser() for each argument.
    // Each of the parameters inside {} are guaranteed to be constructed
    // left to right.
    // Because the compiler knows the number of arguments you
    // get a fixed size array that can be used to count the
    // number of parameters that were actually found.
    auto count[] = {parser(format, value, args)...};

    // Probably need a check for unmatched format parts.

    // The return the number of format parameters matched.
    return std::accumulate(std::begin(count), std::end(count), 0);
}

Am I overlooking useful features in the standard library that would make things easier?

I don't think there is anything you absolutely need.

Should I be using pointers in this way, or am I thinking too much in C?

NO. Absolutely do not use pointers like that.

Prefer to use references. This way you don't need to check for null. You also express your intent much more clearly so there is no confusion on the ownership of the pointer.

Should I consider another approach entirely, like tscanf(format, paramname1, paramname2) >> param1 >> param2?

There have been a couple of attempts like this. boost::format springs to mind. They used % rather than >>. But personally I don't see a need for this. BUT big advancements have come from trying the non obvious (things I would not think of). So please experiment.

So here's what I'm hoping to find out: Is this code idiomatic modern C++?

Pretty much.
You use recursion to handle the multiple arguments. But a better technique may be to use the compiler to build objects to handle each argument. Unfortunately the way you have to defined the interface makes this a bit hard. If we re-consider the interface to make it like C-scanf.

template<typename... Args)
int tscanf(char const* format, char const& value, Args&... args)
{
    // This will call parser() for each argument.
    // Each of the parameters inside {} are guaranteed to be constructed
    // left to right.
    // Because the compiler knows the number of arguments you
    // get a fixed size array that can be used to count the
    // number of parameters that were actually found.
    auto count[] = {parser(format, value, args)...};

    // Probably need a check for unmatched format parts.

    // The return the number of format parameters matched.
    return std::accumulate(std::begin(count), std::end(count), 0);
}

Am I overlooking useful features in the standard library that would make things easier?

I don't think there is anything you absolutely need.

Should I be using pointers in this way, or am I thinking too much in C?

NO. Absolutely do not use pointers like that.

Prefer to use references. This way you don't need to check for null. You also express your intent much more clearly so there is no confusion on the ownership of the pointer.

Should I consider another approach entirely, like tscanf(format, paramname1, paramname2) >> param1 >> param2?

There have been a couple of attempts like this. boost::format springs to mind. They used % rather than >>. But personally I don't see a need for this. BUT big advancements have come from trying the non obvious (things I would not think of). So please experiment.

So here's what I'm hoping to find out: Is this code idiomatic modern C++?

Pretty much.
You use recursion to handle the multiple arguments. But a better technique may be to use the compiler to build objects to handle each argument. Unfortunately the way you have to defined the interface makes this a bit hard. If we re-consider the interface to make it like C-scanf.

template<typename T>
int parser(char const*& format, char const*& value, T& value)
{
     // Parse format and value.
     // convert the first % in format into value and save in value.
     // return 1 if value was correctly parsed otherwise 0
}

template<typename... Args)
int tscanf(char const* format, char const* value, Args&... args)
{
    // This will call parser() for each argument.
    // Each of the parameters inside {} are guaranteed to be constructed
    // left to right.
    // Because the compiler knows the number of arguments you
    // get a fixed size array that can be used to count the
    // number of parameters that were actually found.
    auto count[] = {parser(format, value, args)...};

    // Probably need a check for unmatched format parts.

    // The return the number of format parameters matched.
    return std::accumulate(std::begin(count), std::end(count), 0);
}

Am I overlooking useful features in the standard library that would make things easier?

I don't think there is anything you absolutely need.

Should I be using pointers in this way, or am I thinking too much in C?

NO. Absolutely do not use pointers like that.

Prefer to use references. This way you don't need to check for null. You also express your intent much more clearly so there is no confusion on the ownership of the pointer.

Should I consider another approach entirely, like tscanf(format, paramname1, paramname2) >> param1 >> param2?

There have been a couple of attempts like this. boost::format springs to mind. They used % rather than >>. But personally I don't see a need for this. BUT big advancements have come from trying the non obvious (things I would not think of). So please experiment.

Source Link
Loki Astari
  • 97.7k
  • 5
  • 126
  • 341

So here's what I'm hoping to find out: Is this code idiomatic modern C++?

Pretty much.
You use recursion to handle the multiple arguments. But a better technique may be to use the compiler to build objects to handle each argument. Unfortunately the way you have to defined the interface makes this a bit hard. If we re-consider the interface to make it like C-scanf.

template<typename... Args)
int tscanf(char const* format, char const& value, Args&... args)
{
    // This will call parser() for each argument.
    // Each of the parameters inside {} are guaranteed to be constructed
    // left to right.
    // Because the compiler knows the number of arguments you
    // get a fixed size array that can be used to count the
    // number of parameters that were actually found.
    auto count[] = {parser(format, value, args)...};

    // Probably need a check for unmatched format parts.

    // The return the number of format parameters matched.
    return std::accumulate(std::begin(count), std::end(count), 0);
}

Am I overlooking useful features in the standard library that would make things easier?

I don't think there is anything you absolutely need.

Should I be using pointers in this way, or am I thinking too much in C?

NO. Absolutely do not use pointers like that.

Prefer to use references. This way you don't need to check for null. You also express your intent much more clearly so there is no confusion on the ownership of the pointer.

Should I consider another approach entirely, like tscanf(format, paramname1, paramname2) >> param1 >> param2?

There have been a couple of attempts like this. boost::format springs to mind. They used % rather than >>. But personally I don't see a need for this. BUT big advancements have come from trying the non obvious (things I would not think of). So please experiment.