<p>This is a template for C++ projects.</p>


<h3>Contents</h3>

<ul>
<li><a href="#dirstruct">Directory Structure</a></li>
<li><a href="#markdown">Markdown</a></li>
<li><a href="#cmake">CMake</a></li>
<li><a href="#conan">Conan</a></li>
<li><a href="#git">Git</a></li>
<li><a href="#clang-format">Clang-Format</a></li>
<li><a href="#headers">Header Files</a></li>
<li><a href="#sources">Source Files</a></li>
</ul>


<h3 id="dirstruct">Directory Structure</h3>
<ul>
<li>Code used for testing is separated from the actual source code</li>
<li>A directory exists for each namespace</li>
</ul>

<ul class="dirtree">
<li class="folder">src
  <ul>
  <li class="folder">util
    <ul>
    <li class="file"><a href="#src/util/CMakeLists.txt">CMakeLists.txt</a></li>
    <li class="file"><a href="#src/util/simple_replacer.cpp">simple_replacer.cpp</a></li>
    <li class="file"><a href="#src/util/simple_replacer.hpp">simple_replacer.hpp</a></li>
    </ul>
  </li>
  <li class="file"><a href="#src/CMakeLists.txt">CMakeLists.txt</a></li>
  <li class="file"><a href="#src/main.cpp">main.cpp</a></li>
  </ul>
</li>
<li class="folder">test
  <ul>
  <li class="folder">util
    <ul>
    <li class="file"><a href="#test/util/CMakeLists.txt">CMakeLists.txt</a></li>
    <li class="file"><a href="#test/util/simple_replacer_test.cpp">simple_replacer_test.cpp</a></li>
    </ul>
  </li>
  <li class="file"><a href="#test/CMakeLists.txt">CMakeLists.txt</a></li>
  </ul>
</li>
<li class="file"><a href="#.clang-format">.clang-format</a></li>
<li class="file"><a href="#.gitignore">.gitignore</a></li>
<li class="file"><a href="#CMakeLists.txt">CMakeLists.txt</a></li>
<li class="file"><a href="#README.md">README.md</a></li>
<li class="file"><a href="#conanfile.py">conanfile.py</a></li>
</ul>


<h3 id="markdown">Markdown</h3>
<p>Markdown is a lightweight markup language for text formatting.</p>
<p>Each project should include a readme file with the following information:</p>
<ul>
<li>Description about the project</li>
<li>How the software can be build</li>
<li>Information about running the tests</li>
<li>Usage example to get started</li>
</ul>

<dl class="file" id="README.md">
<dt><code class="filename">README.md</code></dt>
<dd>
<pre class="file"><code class="language-markdown"># HelloWorld

This application prints *Hello World!* on screen.
The intention is to have a template for C++ projects.

## How to build

### CMake

```
mkdir -p build/Release
cd build/Release
cmake ../..
cmake --build . --config Release
```

### Conan

```
mkdir build
cd build
conan install --build=missing ..
conan build ..
```

## Running the tests

```
cd build/Release
ctest
```

## Usage

```
cd build/Release
./bin/hello [name]
```
</code></pre>
</dd>
</dl>

<ul>
<li><a href="https://en.wikipedia.org/wiki/Markdown" target="_blank">
https://en.wikipedia.org/wiki/Markdown</a></li>
<li><a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet" target="_blank">
https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet</a></li>
</ul>


<h3 id="cmake">CMake</h3>
<p>CMake is the de facto standard build system for C++.</p>

<dl class="file" id="CMakeLists.txt">
<dt><code class="filename">CMakeLists.txt</code></dt>
<dd>
<pre class="file"><code class="language-cmake">cmake_minimum_required(VERSION 3.15)

project(HelloWorld CXX)

include(CTest)

find_package(Boost REQUIRED)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

include_directories(src)
add_subdirectory(src)

if(BUILD_TESTING)
    enable_testing()
    add_subdirectory(test)
endif()
</code></pre>
</dd>
</dl>

<dl class="file" id="src/CMakeLists.txt">
<dt><code class="filename">src/CMakeLists.txt</code></dt>
<dd>
<pre class="file"><code class="language-cmake">add_subdirectory(util)

set(hello_SOURCES
    main.cpp)
add_executable(hello ${hello_SOURCES})
target_link_libraries(hello util)

install(TARGETS hello
        RUNTIME DESTINATION bin)
</code></pre>
</dd>
</dl>

<dl class="file" id="src/util/CMakeLists.txt">
<dt><code class="filename">src/util/CMakeLists.txt</code></dt>
<dd>
<pre class="file"><code class="language-cmake">set(util_HEADERS
    simple_replacer.hpp)
set(util_SOURCES
    simple_replacer.cpp)
add_library(util ${util_SOURCES} ${util_HEADERS})
set_target_properties(util PROPERTIES PUBLIC_HEADER "${util_HEADERS}")
target_include_directories(util PRIVATE ${Boost_INCLUDE_DIRS})
target_link_libraries(util ${Boost_LIBRARIES})

install(TARGETS util
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib
        PUBLIC_HEADER DESTINATION include/util)
</code></pre>
</dd>
</dl>

<dl class="file" id="test/CMakeLists.txt">
<dt><code class="filename">test/CMakeLists.txt</code></dt>
<dd>
<pre class="file"><code class="language-cmake">add_subdirectory(util)
</code></pre>
</dd>
</dl>

<dl class="file" id="test/util/CMakeLists.txt">
<dt><code class="filename">test/util/CMakeLists.txt</code></dt>
<dd>
<pre class="file"><code class="language-cmake">add_executable(simple_replacer_test simple_replacer_test.cpp)
target_link_libraries(simple_replacer_test util)
add_test(NAME simple_replacer COMMAND simple_replacer_test)
</code></pre>
</dd>
</dl>

<ul>
<li><a href="https://cmake.org/cmake/help/latest/" target="_blank">
https://cmake.org/cmake/help/latest/</a></li>
<li><a href="https://cmake.org/cmake/help/latest/module/CTest.html" target="_blank">
https://cmake.org/cmake/help/latest/module/CTest.html</a></li>
<li><a href="https://cmake.org/cmake/help/latest/command/install.html#installing-targets" target="_blank">
https://cmake.org/cmake/help/latest/command/install.html#installing-targets</a></li>
</ul>


<h3 id="conan">Conan</h3>
<p>Conan is a package manager for C++.</p>

<dl class="file" id="conanfile.py">
<dt><code class="filename">conanfile.py</code></dt>
<dd>
<pre class="file"><code class="language-python">from conan import ConanFile
from conan.errors import ConanException
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps
from conan.tools.scm import Git
from conan.tools.files import update_conandata


class HelloWorldRecipe(ConanFile):
    name = "helloworld"
    package_type = "application"
    settings = "os", "compiler", "build_type", "arch"

    def export(self):
        git = Git(self, self.recipe_folder)
        scm_url, scm_commit = git.get_url_and_commit()
        self.output.info(f"Obtained URL: {scm_url} and {scm_commit}")
        update_conandata(self, {
            "sources": {"commit": scm_commit, "url": scm_url}
        })

    def source(self):
        git = Git(self)
        sources = self.conan_data["sources"]
        self.output.info(f"Cloning sources from: {sources}")
        git.clone(url=sources["url"], target=".")
        git.checkout(commit=sources["commit"])

    def set_version(self):
        try:
            git = Git(self, self.recipe_folder)
            self.version = git.run("describe --tags")
            if self.version[0] == "v":
                self.version = self.version[1:]
        except ConanException as exc:
            self.output.warning(f"Exception in set_version: {exc}")
            self.version = "undef"

    def requirements(self):
        self.requires("boost/1.81.0")

    def layout(self):
        cmake_layout(self)

    def generate(self):
        deps = CMakeDeps(self)
        deps.generate()
        tc = CMakeToolchain(self)
        tc.generate()

    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()

    def package(self):
        cmake = CMake(self)
        cmake.install()
</code></pre>
</dd>
</dl>

<ul>
<li><a href="https://docs.conan.io/2/index.html" target="_blank">
https://docs.conan.io/2/index.html</a></li>
<li><a href="https://docs.conan.io/2/reference/commands/new.html" target="_blank">
https://docs.conan.io/2/reference/commands/new.html</a></li>
<li><a href="https://docs.conan.io/2/examples/tools/scm/git/capture_scm/git_capture_scm.html" target="_blank">
https://docs.conan.io/2/examples/tools/scm/git/capture_scm/git_capture_scm.html</a></li>
<li><a href="https://docs.conan.io/2/reference/conanfile/methods/set_version.html" target="_blank">
https://docs.conan.io/2/reference/conanfile/methods/set_version.html</a></li>
</ul>


<h3 id="git">Git</h3>
<p>Git is a version control system that tracks changes in code.</p>
<p>The build directory is excluded from tracking changes.</p>

<dl class="file" id=".gitignore">
<dt><code class="filename">.gitignore</code></dt>
<dd>
<pre class="file"><code class="language-plaintext">build
</code></pre>
</dd>
</dl>

<ul>
<li><a href="https://git-scm.com/docs/gitignore" target="_blank">
https://git-scm.com/docs/gitignore</a></li>
</ul>


<h3 id="clang-format">Clang-Format</h3>
<p>Clang-Format is a tool to format code.</p>

<dl class="file" id=".clang-format">
<dt><code class="filename">.clang-format</code></dt>
<dd>
<pre class="file"><code class="language-plaintext">BasedOnStyle: WebKit
NamespaceIndentation: None
</code></pre>
</dd>
</dl>

<ul>
<li><a href="https://clang.llvm.org/docs/ClangFormatStyleOptions.html" target="_blank">
https://clang.llvm.org/docs/ClangFormatStyleOptions.html</a></li>
</ul>


<h3 id="headers">Header Files</h3>

<dl class="file" id="src/util/simple_replacer.hpp">
<dt><code class="filename">src/util/simple_replacer.hpp</code></dt>
<dd>
<pre class="file"><code class="language-cpp">#pragma once

#include &lt;string&gt;

namespace util {

class SimpleReplacer {
public:
    explicit SimpleReplacer(const std::string& content);
    virtual ~SimpleReplacer();

    void replaceAll(const std::string& search, const std::string& replace);
    std::string getContent() const;

private:
    std::string content_;
};

} // namespace util
</code></pre>
</dd>
</dl>


<h3 id="sources">Source Files</h3>

<dl class="file" id="src/main.cpp">
<dt><code class="filename">src/main.cpp</code></dt>
<dd>
<pre class="file"><code class="language-cpp">#include "util/simple_replacer.hpp"
#include &lt;iostream&gt;
#include &lt;string&gt;

int main(int argc, char* argv[])
{
    std::string msg("Hello World!");
    if (argc &gt;= 2) {
        util::SimpleReplacer replacer(msg);
        replacer.replaceAll("World", argv[1]);
        msg = replacer.getContent();
    }
    std::cout &lt;&lt; msg &lt;&lt; std::endl;
}
</code></pre>
</dd>
</dl>

<dl class="file" id="src/util/simple_replacer.cpp">
<dt><code class="filename">src/util/simple_replacer.cpp</code></dt>
<dd>
<pre class="file"><code class="language-cpp">#include "simple_replacer.hpp"
#include &lt;boost/algorithm/string.hpp&gt;

namespace util {

SimpleReplacer::SimpleReplacer(const std::string& content)
    : content_(content)
{
}

SimpleReplacer::~SimpleReplacer() = default;

void SimpleReplacer::replaceAll(const std::string& search,
    const std::string& replace)
{
    boost::replace_all(content_, search, replace);
}

std::string SimpleReplacer::getContent() const
{
    return content_;
}

} // namespace util
</code></pre>
</dd>
</dl>

<dl class="file" id="test/util/simple_replacer_test.cpp">
<dt><code class="filename">test/util/simple_replacer_test.cpp</code></dt>
<dd>
<pre class="file"><code class="language-cpp">#include "util/simple_replacer.hpp"

int main()
{
    std::string content("Just a test.");
    util::SimpleReplacer replacer(content);
    replacer.replaceAll("a", "another");
    std::string result = replacer.getContent();
    std::string expected("Just another test.");
    if (result == expected) {
        return 0;
    }
    return 1;
}
</code></pre>
</dd>
</dl>