Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fmt library integration example #147

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: Install {fmt}
run: sudo apt install libfmt-dev

- name: Install packages
if: matrix.install
run: sudo apt install ${{matrix.install}}
Expand Down Expand Up @@ -151,6 +154,15 @@ jobs:
steps:
- uses: actions/checkout@v2

- uses: microsoft/setup-msbuild@v1.1
- name: Install {fmt}
uses: lukka/run-vcpkg@v6
with:
vcpkgGitCommitId: '88b1071e39f13b632644d9d953738d345a4ac055'
vcpkgDirectory: '${{ runner.workspace }}/vcpkg'
vcpkgTriplet: x64-windows
vcpkgArguments: fmt

- name: Setup Boost
shell: cmd
run: |
Expand Down
70 changes: 70 additions & 0 deletions example/fmtlib_formatter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) 2023 Denis Mikhailov
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <boost/pfr.hpp>
#include <fmt/format.h>
#include <type_traits>

namespace boost::pfr {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

namespace boost::pfr::extension { ??

struct fmtlib_tag;
}

template<class T> struct fmt::formatter<T, char, std::enable_if_t<
boost::pfr::is_reflectable<T, boost::pfr::fmtlib_tag>::value>>
{
constexpr auto parse(format_parse_context& ctx) -> format_parse_context::iterator {
auto it = ctx.begin(), end = ctx.end();

if (it != end && *it != '}') ctx.error_handler().on_error( "invalid format" );

return it;
}

auto format(const T& t, format_context& ctx) const -> format_context::iterator {
using namespace boost::pfr;

auto out = ctx.out();

*out++ = '{';

const char* div = "";
constexpr auto names = names_as_array<T>();

for_each_field(t, [&](const auto& field, auto I) {
out = fmt::format_to(out, "{}", std::exchange(div, ","));
out = fmt::format_to(out, " .{}={}", names[I], field);
});

out = fmt::format_to(out, "{}", std::strlen(div) == 0 ? "}" : " }");

return out;
}
};

struct point
{
int x, y;
};

struct color
{
unsigned char r, g, b;
};

struct line
{
color clr;
point first, last;
};

template<> struct boost::pfr::is_reflectable<point, boost::pfr::fmtlib_tag> : std::integral_constant<bool, true> {};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

template<typename P> struct boost::pfr::is_reflectable<point, P> : std::integral_constant<bool, true> {};
Same for another specializations

template<> struct boost::pfr::is_reflectable<color, boost::pfr::fmtlib_tag> : std::integral_constant<bool, true> {};
template<> struct boost::pfr::is_reflectable<line, boost::pfr::fmtlib_tag> : std::integral_constant<bool, true> {};

int main()
{
fmt::print("{}\n", line{ { 255, 192, 16 }, { 1, 2 }, { 3, 4 } });
}

23 changes: 23 additions & 0 deletions test/appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,19 @@ environment:
TOOLSET: gcc
CXXSTD: 14,1z

cache:
- c:\tools\vcpkg\installed\

before_build:
# Install {fmt} library in order to run examples
# FIXME: To be removed https://help.appveyor.com/discussions/problems/13000-cmake_toolchain_filevcpkgcmake-conflicts-with-cmake-native-findboostcmake"
- ps: 'Write-Host "Installing latest vcpkg.cmake module" -ForegroundColor Magenta'
- appveyor DownloadFile https://raw.githubusercontent.com/Microsoft/vcpkg/master/scripts/buildsystems/vcpkg.cmake -FileName "c:\tools\vcpkg\scripts\buildsystems\vcpkg.cmake"
- set "TRIPLET=x64-windows"
- vcpkg --triplet %TRIPLET% install fmt
- set PATH=C:\Tools\vcpkg\installed\%TRIPLET%\bin;%PATH%
- set VCPKG_I=C:\Tools\vcpkg\installed\%TRIPLET%\include
- set VCPKG_L=C:\Tools\vcpkg\installed\%TRIPLET%\lib
- set BOOST_BRANCH=develop
- if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master
- echo "Testing %BOOST_LIBS_FOLDER%"
Expand All @@ -85,6 +97,17 @@ before_build:
- python tools/boostdep/depinst/depinst.py --git_args "--depth 10 --jobs 2" -I example -I examples %BOOST_LIBS_FOLDER%

build_script:
- xcopy %APPVEYOR_BUILD_FOLDER%\fmt.jam %USERPROFILE%
- ps: |
# Creating %USERPROFILE%/user-config.jam file
@'
import os regex toolset ;
local toolset = [ regex.split [ os.environ TOOLSET ] "-" ] ;
local vcpkg_i = [ os.environ VCPKG_I ] ;
local vcpkg_l = [ os.environ VCPKG_L ] ;
using $(toolset[1]) : $(toolset[2-]:J="-") : ;
using fmt : : <include>$(vcpkg_i) <search>$(vcpkg_l) ;
'@ | sc "$env:USERPROFILE/user-config.jam"
- cmd /c bootstrap
- b2.exe headers
- cd %BOOST%/libs/%BOOST_LIBS_FOLDER%/test
Expand Down
Loading