The Results of the Expressive C++17 Coding Challenge | Fluent{C++}

Jonathan Boccara; The Results of the Expressive C++17 Coding Challenge; In His Blog entitled Fluent{C++}; 2017-10-23.



Fernando B. Giannasi,

  • Brazil (lives in, citizen of)
  • [He's] not […] a professional programmer.
  • Wasn’t even trying
  • One hand tied behind his back,
  • etc.…

Neat code tho.

Problem Statement

A command line tool that takes in a CSV file, overwrites all the data of a given column by a given value, and outputs the results into a new CSV file. Accept the following arguments:

  • the filename of a CSV file,
  • the name of the column to overwrite in that file,
  • the string that will be used as a replacement for that column,
  • the filename where the output will be written.

Details & clarifications in the post.



In His Blog


g++ -std=c++1z -O2 -Wall -pedantic -pthread main.cpp -lstdc++fs && ./a.out
Bad arguments
Usage: ./a.out [IN_FILE] [COLUMN] [NEW_VALUE] [OUT_FILE]
bash: line 7: 31459 Aborted                 (core dumped) ./a.out

Exhibited at coliru


/* Name: Fernando B. Giannasi
 * Email:
 * Features of C++17 used:
 * - std::filesystem
 * - nodiscard and noreturn attributes
 * - structured bindings
 * - string_view
 * - Template argument deduction for class templates
 * - Init-statement for if/switch
 * - std::optional
#include <algorithm>
#include <experimental/filesystem>
#include <fstream>
#include <iostream>
#include <optional>
#include <string>
#include <string_view>
#include <sstream>
#include <utility>
#include <vector>

using namespace std;
namespace fs = std::experimental::filesystem;

[[nodiscard]] auto split_string(const string_view& input, const char delimiter) {
  stringstream ss {};
  vector<string> result;
  // result.reserve(count(begin(input), end(input), delimiter));
  for (string buffer; getline(ss, buffer, delimiter); /*empty*/) {
  return result;

[[nodiscard]] optional<int> get_target_column(ifstream& input, const string_view& label, const char delimiter) {
  string first_line;
  // if-init
  if (getline(input, first_line); first_line.size() == 0) {
    throw runtime_error("Input file missing");
  auto tokens = split_string(first_line, delimiter);
  if (auto it = find(begin(tokens), end(tokens), label); it == tokens.end()) {
    return {}; //return empty optional
  } else {
    return distance(begin(tokens), it);

[[nodiscard]] auto get_file_handlers(const string_view& input, const string_view& output) {
  ifstream in_file{, ios::in};
  if (!in_file.is_open()) {
    throw runtime_error("Unable to open input file");
  ofstream out_file{, ios::out | ios::trunc};
  if (!out_file.is_open()) {
    throw runtime_error("Unable to open output file");
  // template argument deduction for class templates (no make_pair)
  return pair(move(in_file), move(out_file));

void do_work(ifstream& input, ofstream& output, int target_index, const string_view& new_value, const char delimiter) {
  string buffer;
  getline(input, buffer); // for the header line
  output << buffer << endl;
  while (getline(input, buffer)) {
    auto tokens = split_string(buffer, delimiter);
    tokens[target_index] =;
    for (auto& i: tokens) {
      output << i;
      output << (i == tokens.back() ? 'n':delimiter);

[[noreturn]] void usage_terminate(const string_view& progname) noexcept {
  cout << "Usage: " << progname << " [IN_FILE] [COLUMN] [NEW_VALUE] [OUT_FILE]" << endl;

int main(int argc, char* argv[]) {
  try {
    if (argc != 5) {
      throw runtime_error("Bad arguments");
    auto [in_file, out_file] = get_file_handlers(argv[1], argv[4]);
    string_view new_value = argv[3];
    auto target_index = get_target_column(in_file, argv[2], ',');
    if (target_index) {
        do_work(in_file, out_file, *target_index, new_value, ',');
    } else {
        throw runtime_error("Column name doesn’t exist in the input file");
  } catch (runtime_error& e) {
    cout << e.what() << endl;
  return 0;

Trip report: Summer ISO C++ standards meeting (Toronto) | Sutter’s Mill

Herb Sutter; Trip report: Summer ISO C++ standards meeting (Toronto); In His Blog entitled Sutter’s Mill; 2017-07-15.


  • Draft C++20
  • C++17

Separately noted.

A proposal for named arguments for C++ | N4172 | Akhgari, Ballo

N4172Named Arguments; Ehsan Akhgari (Mozilla), Botond Ballo (Mozilla); 2014-10-07.


  • Following Ada, VHDL, etc.
  • Positional arguments precede named arguments.
  • Function names are not part of the function’s type.
  • the name binding operator is : (colon)


void foo(int a, char b, std::string c);
void test() {
 foo(c: "s", a: 1, b: 'c'); // valid
void foo(int x, char y, std::string z) {
void foo(int a, char b, std::string c);
void foo(int a, char b, std::string x);
void bar(int a, char b);void bar(int x, char b);
void test() {
  foo(1, 'c', "s"); // valid
 foo(1, 'c', c: "s"); // invalid -- different names for an argument in multiple declarations 
 foo(1, 'c', x: "s"); // invalid -- different names for an argument in multiple declarations
  bar(1, b: 'c'); // invalid -- different names for an argument in multiple declarations


Issues & Interactions

  • Overload resolution
  • Constructor calls
  • Aggregate initializers
  • Calls through function pointers
  • Perfect forwarding
  • (Backwards) compatibility


  • This feature caters to having functions with many parameters – a programming style that should be discouraged.
  • This proposal competes with C99 designated initializers, which are being proposed for C++.
  • Named arguments make parameter names part of a function’s interface, so that changing the parameter names can affect call sites


  • Non-trailing default arguments
  • Named template arguments


  • A study(some grepping) on open source parameter name changes.
    • Eigen
    • wxWidgets
    • boost