9

printf完全転送を利用する (ロギングに使用される) のような関数があるとします。

template<typename... Arguments>
void awesome_printf(std::string const& fmt, Arguments&&... args)
{
    boost::format f(fmt);
    f % /* How to specify `args` here? */;
    BlackBoxLogFunction(boost::str(f).c_str());
}

(私はこれをコンパイルしませんでしたが、私の実際の機能はこのガイドラインに従います)

可変引数を boost::format 変数に「展開」するにはどうすればよいですfか?

4

3 に答える 3

12

可変個引数テンプレートでよくあるように、再帰を使用できます。

std::string awesome_printf_helper(boost::format& f){
    return boost::str(f);
}

template<class T, class... Args>
std::string awesome_printf_helper(boost::format& f, T&& t, Args&&... args){
    return awesome_printf_helper(f % std::forward<T>(t), std::forward<Args>(args)...);
}

template<typename... Arguments>
void awesome_printf(std::string const& fmt, Arguments&&... args)
{
    boost::format f(fmt);

    auto result = awesome_printf_helper(f, std::forward<Arguments>(args)...);

    // call BlackBoxLogFunction with result as appropriate, e.g.
    std::cout << result;
}

デモ


C++17 では、単純(f % ... % std::forward<Arguments>(args));に実行できます。

于 2014-09-16T02:36:43.820 に答える
11

私はいくつかのグーグルを行い、興味深い解決策を見つけました:

#include <iostream>
#include <boost/format.hpp>

template<typename... Arguments>
void format_vargs(std::string const& fmt, Arguments&&... args)
{
    boost::format f(fmt);
    int unroll[] {0, (f % std::forward<Arguments>(args), 0)...};
    static_cast<void>(unroll);

    std::cout << boost::str(f);
}

int main()
{
    format_vargs("%s %d %d", "Test", 1, 2);
}

これが推奨される解決策かどうかはわかりませんが、うまくいくようです。static_castGCCで未使用の変数の警告を黙らせるために必要と思われるハッキーな使用法は好きではありません。

于 2014-09-16T02:43:29.557 に答える