第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