Per Møldrup-Dalum

An Evening With C++

Today, I happened to come across a LinkedIn post linking to an article by Bjarne Stoustrup with the title 21th Century C++ (Stoustrup, 2025) which caught my eye.

Why? Well, Once upon a time I programmed in C++, I can be a bit nostalgic, and also get a bit weary of all the new and shiny tools coming out all the time. Often I think about whether we really need them instead of building upon what we have. But the kids do not want to use the same tools their parents used, and instead they build their own.

So, I started to read the article and on the first page, Stoustrup presents this elegant implementation of a classic tool: print all unique lines in a file.

nota bene

In awk, this is done with just this small piece of code: !a[$0]++ which is also from Stoustrups article. See the end of the article for more.


import std;
using namespace std;

int main()
{
  unordered_map<string,int> m;
  for (string line; getline(cin,line);)
    if (m[line]++ == 0)
      cout << line << '\n';
}
        

Okay, this did not look like the C++ I remembered, so I wanted to try to compile it and maybe play a bit with this new C++. But then


 >: c++ unique-lines.cpp 
c++ unique-lines.cpp 
unique-lines.cpp:1:1: error: unknown type name 'std'
    1 | std import;
      | ^
unique-lines.cpp:2:17: warning: using directive refers to implicitly-defined namespace
      'std'
    2 | using namespace std;
      |                 ^
unique-lines.cpp:6:17: error: use of undeclared identifier 'string'
    6 |   unordered_map<string,int> m;
      |                 ^
unique-lines.cpp:7:8: error: unknown type name 'string'
    7 |   for (string line; getline(cin,line);)
      |        ^
unique-lines.cpp:7:29: error: use of undeclared identifier 'cin'
    7 |   for (string line; getline(cin,line);)
      |                             ^
unique-lines.cpp:9:7: error: use of undeclared identifier 'cout'
    9 |       cout << line << '\n';
      |       ^
1 warning and 5 errors generated.

Wups! Apparently my C++ compiler had no idea about what I was trying to compile. Okay, off to the web to look for an explanation and pretty quick I ended up with this search history:


(ingen titel) 2.webloc
(ingen titel).webloc
21st Century C++ (Feb. 2025) by Bjarne Stoustrup | Hacker News.webloc
21st Century C++ at DuckDuckGo 2.webloc
21st Century C++ at DuckDuckGo.webloc
21st Century C++ – Communications of the ACM 2.webloc
21st Century C++ – Communications of the ACM.webloc
21st century bjarne stoustrup linkedin at DuckDuckGo 2.webloc
21st century bjarne stoustrup linkedin at DuckDuckGo.webloc
Bjarne Stoustrup's Homepage.webloc
C++ Compilers.webloc
C++ compiler support - cppreference.com.webloc
Clang - C++ Programming Language Status.webloc
Clang - Features and Goals.webloc
Clang C Language Family Frontend for LLVM.webloc
Feature testing (since C++20) - cppreference.com.webloc
Google.webloc
Kindle E-Reader Software Updates - Amazon Customer Service.webloc
The Standard - Standard C++.webloc
Tutorial- Import the standard library (STL) using modules from the command line (C++) | Microsoft Le….webloc
Why is there still such poor compiler support for C++ Modules? - r-cpp.webloc
c++ - How to use C++20 modules with GCC? - Stack Overflow.webloc
c++ standard at DuckDuckGo 2.webloc
c++ standard at DuckDuckGo.webloc
c++ use import std at DuckDuckGo 2.webloc
c++ use import std at DuckDuckGo.webloc
clang C++23 at DuckDuckGo 2.webloc
clang C++23 at DuckDuckGo.webloc
extension af c++ program files at DuckDuckGo 2.webloc
extension af c++ program files at DuckDuckGo.webloc
filenames - C++ code file extension? What is the difference between .cc and .cpp - Stack Overflow.webloc
gcc g++ use modules at DuckDuckGo 2.webloc
gcc g++ use modules at DuckDuckGo.webloc
hos to use c++23 in clang at DuckDuckGo 2.webloc
hos to use c++23 in clang at DuckDuckGo.webloc
how to use import instead of #include in modern c++ at DuckDuckGo 2.webloc
how to use import instead of #include in modern c++ at DuckDuckGo.webloc
unique-lines.cpp-1-1- error- unknown type name 'import' - Google Search.webloc
unique-lines.cpp-1-1- error- unknown type name 'import' at DuckDuckGo 2.webloc
unique-lines.cpp-1-1- error- unknown type name 'import' at DuckDuckGo.webloc
which c++ compilers support modules at DuckDuckGo 2.webloc
which c++ compilers support modules at DuckDuckGo.webloc
which compiler use stroustrup at DuckDuckGo 2.webloc
which compiler use stroustrup at DuckDuckGo.webloc
        

Intermezzo: make my search history computable

So, how can one go from the search history above to something, that can be saved and used programmatically. First off, it's quite easy to drag the history entries from Safari into a file folder and end up with a bunch of .webloc files like in the above list. But how do one go from those files to the actual URLs?


In[1]:= SetDirectory["~/2025"];

In[2]:= FileNames[]//First
Out[2]= 21st century bjarne stoustrup linkedin at DuckDuckGo 2.webloc

In[3]:= FilePrint@%
         bplist00Ñ\.01\.02SURL_\.10Fhttps://duckduckgo.com/?q=21st+century+bjarne+stoustrup+linkedin&t=osx\.08\.0b\.0f

In[4]:= Read[%2]
During evaluation of In[4]:= $CharacterEncoding::utf8: The byte sequence {209,1} could not be interpreted as a character in the UTF-8 character encoding.
During evaluation of In[4]:= $CharacterEncoding::utf8: The byte sequence {209,1} could not be interpreted as a character in the UTF-8 character encoding.
During evaluation of In[4]:= Read::readt: "Invalid input found when reading \!\(\*RowBox[{\"\\\"bplist00Ñ\.02SURL_\.10Fhttps://duckduckgo.com/?q=21st+century+bjarne+stoustrup+linkedin&t=osx\\b\.0b\.0f\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\.01\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\.03\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000\\\\\\\\:0000X\\\\n\\\"\"}]\) from \!\(\*RowBox[{\"\\\"21st century bjarne stoustrup linkedin at DuckDuckGo 2.webloc\\\"\"}]\)."
Out[4]= $Failed
        
nota bene

This code and more below is written in The Wolfram Language, which is my preferred platform for doing general computational stuff.

Alas, the files are in a binary format. Again, off to the web to learn about this format. I quickly realised that this off course was Apple property files in binary format. Years ago I worked a bit with such files, but back then they were in XML format. So, when I knew the file type, it became easy to convert them to XML:


>: for f in *.webloc
do
   plutil -convert xml1 $f
done

I could now easy read the XML files and transform their content into a simple list of URLs and put that list on the clipboard for pasting it into this HTML file:


RunProcess["pbcopy","StandardError",
   ExportString[
      First[
         Cases[
            Import[#,"XML"],
            XMLElement["string",_,{url_}]:>url,
            Infinity
         ]
      ]&/@FileNames[],
      "Text"
   ]
]

So, here is my search history through the web in order to find out why Stoustrups code didn't work:


https://duckduckgo.com/?q=21st+century+bjarne+stoustrup+linkedin&t=osx
https://duckduckgo.com/?q=21st+century+bjarne+stoustrup+linkedin&t=osx&ia=web
https://duckduckgo.com/?q=21st+Century+C%2B%2B&t=osx
https://duckduckgo.com/?q=21st+Century+C%2B%2B&t=osx&ia=web
https://news.ycombinator.com/item?id=42946321
https://cacm.acm.org/blogcacm/21st-century-c/
https://cacm.acm.org/blogcacm/21st-century-c/#refer
https://stroustrup.com/index.html
https://en.cppreference.com/w/cpp/compiler_support
https://stroustrup.com/compilers.html
https://stackoverflow.com/questions/62765630/how-to-use-c20-modules-with-gcc
https://duckduckgo.com/?q=clang+C%2B%2B23&t=osx
https://duckduckgo.com/?q=clang+C%2B%2B23&t=osx&ia=web
https://clang.llvm.org/
https://clang.llvm.org/cxx_status.html
https://clang.llvm.org/features.html
https://duckduckgo.com/?q=c%2B%2B+standard&t=osx
https://duckduckgo.com/?q=c%2B%2B+standard&t=osx&ia=web
https://duckduckgo.com/?q=c%2B%2B+use+import+std&t=osx
https://duckduckgo.com/?q=c%2B%2B+use+import+std&t=osx&ia=web
https://duckduckgo.com/?q=extension+af+c%2B%2B+program+files&t=osx
https://duckduckgo.com/?q=extension+af+c%2B%2B+program+files&t=osx&ia=web
https://en.cppreference.com/w/cpp/feature_test#cpp_lib_modules
https://stackoverflow.com/questions/1545080/c-code-file-extension-what-is-the-difference-between-cc-and-cpp
https://duckduckgo.com/?q=gcc+g%2B%2B+use+modules&t=osx
https://duckduckgo.com/?q=gcc+g%2B%2B+use+modules&t=osx&ia=web
https://www.google.com/?client=safari
https://duckduckgo.com/?q=hos+to+use+c%2B%2B23+in+clang&t=osx
https://duckduckgo.com/?q=hos+to+use+c%2B%2B23+in+clang&t=osx&ia=web
https://duckduckgo.com/?q=how+to+use+import+instead+of+%23include+in+modern+c%2B%2B&t=osx
https://duckduckgo.com/?q=how+to+use+import+instead+of+%23include+in+modern+c%2B%2B&t=osx&ia=web
http://clang.llvm.org/
https://isocpp.org/std/the-standard
https://learn.microsoft.com/en-us/cpp/cpp/tutorial-import-stl-named-module?view=msvc-170
https://duckduckgo.com/?q=unique-lines.cpp%3A1%3A1%3A+error%3A+unknown+type+name+%27import%27&t=osx
https://duckduckgo.com/?q=which+c%2B%2B+compilers+support+modules&t=osx
https://duckduckgo.com/?q=which+c%2B%2B+compilers+support+modules&t=osx&ia=web
https://duckduckgo.com/?q=which+compiler+use+stroustrup&t=osx
https://duckduckgo.com/?q=which+compiler+use+stroustrup&t=osx&ia=web
https://www.reddit.com/r/cpp/comments/ok8o4t/why_is_there_still_such_poor_compiler_support_for/

Back to the main story

The first line in Stoustrups C++ code utilises C++ modules, that, even though they became part of the C++ standard in 2020, are not yet implemented in the two main C++ compilers on my laptop: Apple's clang++ and g++. At least that's what I inferred from a few experiments, readings of the --help output, and from the web.

So, one might say, that it's very easy for Stoustrup to complain and worry about why people still write old-fashioned C++ code, when the "new" functionality isn't available yet...

I then did one more search, and ended on Stackoverflow: apple-clang-13-c20-module-support-missing and decided to install yet another C++ compiler: brew install llvm. Then, with a bit of help from ChatGPT, I changed Stoustrups example to this:


import <iostream>;
import <unordered_map>  // Explicitly import unordered_map
using namespace std;

/*
  dette er linje 1
  dette er linje 1
  dette er linje 1
  dette er linje 2
*/

int main()
{
  unordered_map<string,int> m;
  for (string line; getline(cin,line);)
    if (m[line]++ == 0)
      cout << line << '\n';
}

compiled it with the newly installed Homebrew version of llvm


clang++ -std=c++2a -fmodules -o unique-lines unique-lines.cpp

and got the correct result:


>: ./unique-lines < unique-lines.cpp
import <iostream>;
import <unordered_map>;  // Explicitly import unordered_map
using namespace std;

/*
  dette er linje 1
  dette er linje 2
*/
int main()
{
  unordered_map<string,int> m;
  for (string line; getline(cin,line);)
    if (m[line]++ == 0)
      cout << line << '\n';
}

Now, it's time to read the rest of Stoustrups article to maybe learn why import std; doesn't work, but import <iostream> and import <unordered_map>; is necessary. Oh, I also just wanted to test whether the awk code also works as stated:


 >: awk '!a[$0]++' < unique-lines.cpp 
import <iostream>;
import <unordered_map>;  // Explicitly import unordered_map
using namespace std;

/*
  dette er linje 1
  dette er linje 2
*/
int main()
{
  unordered_map<string,int> m;
  for (string line; getline(cin,line);)
    if (m[line]++ == 0)
      cout << line << '\n';
}

Yup! correct result. Hooray for old school 😃

Bibliography