Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
第30回 可変長引数テンプレート応用編(C++版お手軽printf関数)
cmake_minimum_required(VERSION 3.5.1)
project(sample)
find_package(Boost)
include_directories("${Boost_INCLUDE_DIR}")
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /EHsc")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
endif()
add_executable(sample main.cpp xprintf.cpp xprintf.h)
使用許諾書
・本ソフトウェアは、ご自由にお使いください。
・本ソフトウェアは、あるがままの姿で提供いたします。明示黙示を問わず、瑕疵がないこと、特定の目的に適合すること、使用地域における法令の規制等に合致すること、その他一切の保証をいたしません。
・本ソフトウェアについては、無償で提供するものですので、何らかの不具合が発生した場合であっても、セオライドテクノロジーは、何らの責任も負いません。使用するかどうかのご判断も、ご自身でお願いいたします。
・本ソフトウェアの利用により、お客様のハードウェア機器又はデータ等に支障が生じた場合でも、セオライド テクノロジーは一切その責任を負いません。データのバックアップ等については、お客様の責任において行ってください。
・本ソフトウェアについては、第三者との間で著作権その他知的財産権上の紛争、
・製造物責任法に基づく紛争等が生じた場合でも、セオライド テクノロジーは一切その責任を負いません。
・上記の他、本ソフトウェアに関連して、直接的、もしくは、間接的に何らかの損害が発生したとしても、セオライド テクノロジーは、一切の責任を負いません。
・セオライドテクノロジーは、本ソフトウェアに関する技術的サポートは行いません。
#include <iostream>
#include "xprintf.h"
#ifdef DEBUG
#define DEBUG_LOG(...)
#else
#define DEBUG_LOG(...) std::cout << __FILE__ << "(" << __LINE__ << ") : " << xprintf(__VA_ARGS__)
#endif
enum class Enum { Idle, Test };
class Ratio
{
int mFraction;
int mDenominator;
public:
Ratio(int iFraction, int iDenominator) :
mFraction(iFraction), mDenominator(iDenominator)
{ }
friend std::ostream& operator<<(std::ostream& iOStream, Ratio const& iRatio)
{
iOStream << iRatio.mFraction << "/" << iRatio.mDenominator;
return iOStream;
}
};
int main()
{
std::cout << xprintf("%10s = %6.2f\n", "result", 2345.678);
DEBUG_LOG("%10s = %10.2f\n", "result", 3456.789);
Enum aEnum = Enum::Test;
DEBUG_LOG("%10s = %10d\n", "aEnum", aEnum);
Ratio aRatio(16, 9);
DEBUG_LOG("%10s = %10s\n", "aRatio", aRatio);
std::string aString="test";
DEBUG_LOG("%10s = %10s\n", "aString", aString);
}
#include <boost/format.hpp>
#include "xprintf.h"
namespace internal
{
std::string getString(boost::format& iFormat)
{
return iFormat.str();
}
template<typename tType>
boost::format& output(boost::format& iFormat, tType iParam)
{
return iFormat % iParam;
}
boost::format& makeFormat(std::string const& iFormat)
{
static boost::format aFormat("");
aFormat.parse(iFormat);
return aFormat;
}
// 明示的実体化
template boost::format& output(boost::format& iFormat, bool iParam);
template boost::format& output(boost::format& iFormat, char iParam);
template boost::format& output(boost::format& iFormat, signed char iParam);
template boost::format& output(boost::format& iFormat, short iParam);
template boost::format& output(boost::format& iFormat, int iParam);
template boost::format& output(boost::format& iFormat, long iParam);
template boost::format& output(boost::format& iFormat, long long iParam);
template boost::format& output(boost::format& iFormat, unsigned char iParam);
template boost::format& output(boost::format& iFormat, unsigned short iParam);
template boost::format& output(boost::format& iFormat, unsigned int iParam);
template boost::format& output(boost::format& iFormat, unsigned long long iParam);
template boost::format& output(boost::format& iFormat, float iParam);
template boost::format& output(boost::format& iFormat, double iParam);
template boost::format& output(boost::format& iFormat, long double iParam);
template boost::format& output(boost::format& iFormat, char const* iParam);
}
#include <type_traits>
#include <sstream>
namespace boost
{
template<class charT, class Traits, class Alloc> class basic_format;
typedef basic_format<char, std::char_traits<char>, std::allocator<char>> format;
}
namespace internal
{
std::string getString(boost::format& iFormat);
template<typename tType>
boost::format& output(boost::format& iFormat, tType iParam);
boost::format& makeFormat(std::string const& iFormat);
// ユーザ定義型対応
template<typename tType, typename tEnable=void>
struct Out
{
static boost::format& put(boost::format& iFormat, tType& iParam)
{
std::stringstream ss;
ss << iParam;
return output(iFormat, ss.str().c_str());
}
};
template<typename tType>
struct Out<tType, typename std::enable_if<std::is_arithmetic<tType>::value>::type>
{
static boost::format& put(boost::format& iFormat, tType& iParam)
{
return output(iFormat, iParam);
}
};
// scoped enum型にも対応
template<typename tType>
struct Out<tType, typename std::enable_if<std::is_enum<tType>::value>::type>
{
static boost::format& put(boost::format& iFormat, tType& iParam)
{
return output(iFormat, static_cast<typename std::underlying_type<tType>::type>(iParam));
}
};
inline std::string xprintf_impl(boost::format& iFormat)
{
return getString(iFormat);
}
template<typename tFirst, typename... tParams>
inline std::string xprintf_impl(boost::format& iFormat, tFirst iFirst, tParams... iParams)
{
return xprintf_impl(Out<tFirst>::put(iFormat, iFirst), iParams...);
}
}
template<typename... tParams>
inline std::string xprintf(std::string const& iFormat, tParams... iParams)
{
return internal::xprintf_impl(internal::makeFormat(iFormat), iParams...);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment