#pragma once
/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   2002/X/X - 2016/12/29
/// 
/// @brief  基本定義。
/// 
/// ****************************************************************************


#include <string>
#include <tchar.h>
#include <stdio.h>
#include <fstream>
#include <math.h>
#include <typeinfo>
#include <exception>
#include <stdarg.h>
#include <vector>
#include <array>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <algorithm>
#include <memory>
#include <chrono>
#include <type_traits>
#include <cassert>
#include <thread>
#include <mutex>
#include <utility>



// C+-?
//#include "c_plusminus.h"

namespace CPL {

//#define _SPRINTF_S
//#define _SSCANF_S

// CPL_DEBUG : デバッグモード識別用
#if defined(_DEBUG) || defined(DEBUG)
#   define CPL_DEBUG
#else
#   define CPL_RELEASE
#endif

// CPL_UNICODE : ユニコード文字セット識別用
#if defined(UNICODE) || defined(_UNICODE)
#   define CPL_UNICODE
#endif

// CPL_PLATFORM_64 : 64ビットコンパイル識別用
#if defined(_M_X64) || defined(WIN64) || defined(_WIN64)
#   define CPL_PLATFORM_64
#endif

// Windows 判定用
#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
#   define CPL_WINDOWS
#endif

// 何もなしマクロ引数用。
#define CPL_NONE

//
#if defined(__clang__) || defined(__GNUC__)
#define CPL_ARGS(...) ,##__VA_ARGS__
#elif defined(_MSC_VER)
#define CPL_ARGS(...) ,__VA_ARGS__
#endif

#define CPL_STRING_(s) #s
#define CPL_STRING(s) CPL_STRING_(s)
#define CPL_ONE(a) a
#define CPL_PAIR_(a,b) a##b
#define CPL_PAIR(a,b) CPL_PAIR_(a,b)

//#ifdef _MSC_VER
//#define CPL_SPRINTF_A(dest, format, ...) sprintf_s<sizeof(dest)>(dest, format, __VA_ARGS__)
//#define CPL_SPRINTF_W(dest, format, ...) swprintf_s<sizeof(dest)/2>(dest, format, __VA_ARGS__)
//#endif
//#if defined(__clang__) || defined(__GNUC__)
#define CPL_SPRINTF_A(dest, ...) sprintf_s<sizeof(dest)>(dest, __VA_ARGS__)
#define CPL_SPRINTF_W(dest, ...) swprintf_s<sizeof(dest)/2>(dest, __VA_ARGS__)
//#endif

#define CPL_SSCANF_A(src, format, ...) sscanf_s(src, format, __VA_ARGS__)
#define CPL_SSCANF_W(src, format, ...) swscanf_s(src, format, __VA_ARGS__)

#define CPL_REMOVE_A(filepath) remove(filepath)
#define CPL_REMOVE_W(filepath) _wremove(filepath)

#   define CPL_UC_(x) L##x
#   define ToUC(x) CPL_UC_(x)
#ifdef CPL_UNICODE
//#ifdef _MSC_VER
//#   define CPL_SPRINTF(dest, format, ...) CPL_SPRINTF_W(dest, format, __VA_ARGS__)
//#   define CPL_SSCANF(src, format, ...)   CPL_SSCANF_W(src, format, __VA_ARGS__)
//#endif
//#if defined(__clang__) || defined(__GNUC__)
#   define CPL_SPRINTF(dest, ...) CPL_SPRINTF_W(dest, __VA_ARGS__)
#   define CPL_SSCANF(src, ...)   CPL_SSCANF_W(src, __VA_ARGS__)
//#endif
#   define CPL_REMOVE(filepath) CPL_REMOVE_W(filepath)
#   define SwS(x) CPL_UC_(x)
#   define SwS_toI(x) _wtoi(x)
#   define SwS_toF(x) _wtof(x)
#   define SwS_toI64(x) _wtoi64(x)
#else
#   define CPL_SPRINTF(dest, format, ...) CPL_SPRINTF_A(dest, format, __VA_ARGS__)
#   define CPL_SSCANF(src, format, ...)   CPL_SSCANF_A(src, format, __VA_ARGS__)
#   define CPL_REMOVE(filepath) CPL_REMOVE_A(filepath)
#   define SwS(x) x
#   define SwS_toI(x) atoi(x)
#   define SwS_toF(x) atof(x)
#   define SwS_toI64(x) _atoi64(x)
#endif


#ifdef CPL_THROW_DEFINED // CorePLiの例外指定を有効にする場合、定義してください
#   define CPL_THROW_RESTRICTION(x) throw (x)
#else
#   define CPL_THROW_RESTRICTION(x)
#endif

//#define VIRTUAL_FUNCTION(type,name) virtual type name

//#define CPL_VL(x) virtual x

// 関数名マクロ
#ifdef __func__
#define CPL_FUNCNAME __func__
#endif

#ifndef CPL_FUNCNAME
#ifdef __FUNC__
#define CPL_FUNCNAME __FUNC__
#endif
#endif

#ifndef CPL_FUNCNAME
#ifdef __FUNCTION__
#define CPL_FUNCNAME __FUNCTION__
#endif
#endif

#ifndef CPL_FUNCNAME
#define CPL_FUNCNAME ""
#endif

// クラス名
#define CPL_CLASSNAME (typeid(*this).name())

// typedefもどき（コンパイラの文字数制限においてデバッグが困難にならないよう）
//#define CPL_TYPEDEF( retype, newname )\
//  struct newname {\
//    retype Element;\
//    operator retype&(){ return Element; }\
//    operator retype const&() const { return Element; }\
//    newname(){}\
//    template<class T0> newname( T0 const& a ) : Elment(a) {}\
//    template<class T0, class T1> newname( T0 const& a, T1 const& b ) : Elment(a,b) {}\
//    template<class T0, class T1, class T2> newname( T0 const& a, T1 const& b, T2 const& c ) : Elment(a,b,c) {}\
//  }

// _____________________________________________________________________________
/// @brief シングルトン生成マクロ。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_SINGLETON(type,name)\
  static type& name(){\
    static type obj;\
    return obj;\
  }

// _____________________________________________________________________________
/// @brief シングルトン生成マクロ（配列仕様）
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_SINGLETON_ARRAY(type,name,num)\
  static type& name(int idx){\
    static type obj[ num ];\
    return obj[ idx ];\
  }


// _____________________________________________________________________________
/// @brief シングルトン生成マクロ（初期化付き）
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_SINGLETON_INIT(type,name, ...)\
  static type& name(){\
    static type obj{ __VA_ARGS__ };\
    return obj;\
  }


// _____________________________________________________________________________
/// @brief シングルトン生成マクロ（配列初期化付き）
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_SINGLETON_ARRAY_INIT(type,name,num, ...)\
  static type& name(int idx){\
    static type obj[ num ] = { __VA_ARGS__ };\
    return obj[ idx ];\
  }



// _____________________________________________________________________________
/// @brief スレッドローカルシングルトン生成マクロ。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_THREAD_SINGLETON(type,name)\
  static type& name(){\
    static thread_local type data;\
    return data;\
  }

// _____________________________________________________________________________
/// @brief スレッドローカルシングルトン生成マクロ。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_THREAD_SINGLETON_ARRAY(type,name,num)\
  static type& name(int idx){\
    static thread_local type data[num];\
    return data[idx];\
  }


// _____________________________________________________________________________
/// @brief １度だけ処理するブロック用マクロ。
/// 括弧()内に処理を書く。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_BLOCK_ONCE_(SIG)\
  static std::mutex cpl_mutex_##SIG;\
  static thread_local bool cpl_lock_##SIG = (cpl_mutex_##SIG.lock(),true); (void)cpl_lock_##SIG;\
  static bool cpl_init_##SIG = false;\
  static thread_local auto cpl_unlock_##SIG = cpl_init_##SIG ? (cpl_mutex_##SIG.unlock(),true) : false; (void)cpl_unlock_##SIG;\
  for(; cpl_init_##SIG==0; cpl_init_##SIG=true, cpl_mutex_##SIG.unlock() )

#define CPL_BLOCK_ONCE__(x) CPL_BLOCK_ONCE_(x)

// _____________________________________________________________________________
/// @brief １度だけ処理するブロック用マクロ。
/// 括弧()内に処理を書く。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_BLOCK_ONCE CPL_BLOCK_ONCE__(__COUNTER__)


// _____________________________________________________________________________
/// @brief スレッド毎に１度だけ処理するブロック用マクロ。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_BLOCK_ONCE_THREAD_(SIG)\
  static thread_local int cpl_once_block_thread_##SIG = 1;\
  for(; cpl_once_block_thread_##SIG; --cpl_once_block_thread_##SIG )
#define CPL_BLOCK_ONCE_THREAD__(X) CPL_BLOCK_ONCE_THREAD_(X)

// _____________________________________________________________________________
/// @brief スレッド毎に１度だけ処理するブロック用マクロ。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_BLOCK_ONCE_THREAD CPL_BLOCK_ONCE_THREAD__(__COUNTER__)

// _____________________________________________________________________________
/// @brief １度だけ処理するブロック用マクロ。
/// 
/// 例
/// @code
/// CPL_BLOCK_ONCE2(f0)
/// {
///   /* ここに処理を記述 */
///   return true;
/// }();
/// @endcode
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_BLOCK_ONCE2_(SIG_) static bool SIG_ = [&]()->bool
#define CPL_BLOCK_ONCE2 CPL_BLOCK_ONCE2_(CPL_PAIR(cpl_block_once2_,__COUNTER__))

// _____________________________________________________________________________
/// @brief スレッド毎に１度だけ処理するブロック用マクロ。
/// 
/// 例
/// @code
/// CPL_BLOCK_ONCE_THREAD2(f0)
/// {
///   /* ここに処理を記述 */
///   return true;
/// }();
/// @endcode
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_BLOCK_ONCE_THREAD2_(SIG_) static thread_local bool SIG_ = [&]()->bool
#define CPL_BLOCK_ONCE_THREAD2 CPL_BLOCK_ONCE_THREAD2_(CPL_PAIR(cpl_block_once_thread2_,__COUNTER__))


// _____________________________________________________________________________
/// @brief １度だけ呼び出す。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class Func, class...T_Params> inline
bool CallOnce( Func func, T_Params&&... in_args )
{
  CPL_BLOCK_ONCE2
  {
    func( std::forward<T_Params>(in_args)... );
    return true;
  }();
  return true;
}

// _____________________________________________________________________________
/// @brief スレッド毎に１度だけ呼び出す。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class Func, class...T_Params> inline
bool CallOnceThread( Func func, T_Params&&... in_args )
{
  CPL_BLOCK_ONCE_THREAD2
  {
    func( std::forward<T_Params>(in_args)... );
    return true;
  }();
  return true;
}



// ↓ 適当なものなので、気分で変更・削除される可能性あり ******************************************



// nullポインタ参照回避？
#define CPL_SAFE_PTR(ptr) if( auto cpl_tmp_ptr01306091134_ = (ptr) ) cpl_tmp_ptr01306091134_

//#ifndef ef
//#   define ef else if
//#endif

#ifndef cpl_cv
#   define cpl_cv const volatile
#endif

// ↑ *********************************************************************************************


// _____________________________________________________________________________
/// @brief ループマクロ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_LOOP(N) for(size_t cplloopcounter_=(N); cplloopcounter_; --cplloopcounter_)


// _____________________________________________________________________________
/// @brief ループマクロ インデックス付き
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_LOOP2(N,I) for(auto I##_end_=(N), I=I##_end_-I##_end_; I<I##_end_; ++I)


// _____________________________________________________________________________
/// @brief 逆ループマクロ　インデックス付き
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_LOOP2R(N,I) for(auto I=(N); I--;)


//// _____________________________________________________________________________
///// @brief ループマクロ イテレータ版
//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//#define CPL_LOOP_ITR( obj, itr_name )\
//  for( auto itr_name = obj.begin(); itr_name != obj.end(); ++itr_name )


// _____________________________________________________________________________
/// @brief 単純なメンバ設定関数の定義簡易化用マクロ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_DEF_SET_MEMBER(type, func_name, param_name)\
void func_name( CPL::_in<type> in_##param_name ){ m_##param_name = in_##param_name; }


// _____________________________________________________________________________
/// @brief 単純なメンバ取得関数の定義簡易化用マクロ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_DEF_GET_MEMBER(type, func_name, member_name)\
CPL::ref<type>  func_name()       { return m_##member_name; }\
CPL::cref<type> func_name() const { return m_##member_name; }

// _____________________________________________________________________________
/// @brief 単純なメンバ設定／取得関数の定義簡易化用マクロ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_DEF_SETGET_MENBER(type, common_func_name, param_name)\
CPL_DEF_SET_MEMBER(type, Set##common_func_name, param_name)\
CPL_DEF_GET_MEMBER(type, Get##common_func_name, param_name)


// _____________________________________________________________________________
/// @brief 単純な静的メンバ設定関数の定義簡易化用マクロ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_DEF_SET_STATIC_MEMBER(type, func_name, param_name)\
static void func_name( type in_##param_name ){ m_##param_name = in_##param_name; }


// _____________________________________________________________________________
/// @brief 単純な静的メンバ取得関数の定義簡易化用マクロ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_DEF_GET_STATIC_MEMBER(type, func_name, member_name)\
static type func_name(){ return member_name; }

  

// _____________________________________________________________________________
/// @brief CV修飾有無４パターン簡易定義化用マクロ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_DEF_CV4TYPES_MEMBER(type, func_name, contents)\
  type func_name          { return (contents); }\
  type func_name const    { return (contents); }\
  type func_name volatile { return (contents); }\
  type func_name cpl_cv   { return (contents); }

// CV修飾有無４パターン簡易定義化用マクロ（クリティカルセクション付）
#define CPL_DEF_CV4TYPES_MEMBER_MT(type, func_name, type_cs, contents)\
  type func_name          { return (contents); }\
  type func_name const    { return (contents); }\
  type func_name volatile { type_cs cs; return (contents); }\
  type func_name cpl_cv   { type_cs cs; return (contents); }


typedef char               S8;
typedef unsigned char      U8;
typedef short              S16;
typedef unsigned short     U16;
typedef int                S32;
typedef unsigned int       U32;
typedef long long          S64;
typedef unsigned long long U64;
//typedef __int128           S128;
//typedef unsigned __int128  U128;

#if defined(CPL_PLATFORM_64)
  typedef S64 SDEF;
  typedef U64 UDEF;
#else
  typedef S32 SDEF;
  typedef U32 UDEF;
#endif

const U8     INVALID_INDEX8  = (U8)-1;
const U16    INVALID_INDEX16 = (U16)-1;
const U32    INVALID_INDEX32 = (U32)-1;
const U64    INVALID_INDEX64 = (U64)-1L;
const size_t INVALID_INDEX   = (size_t)-1L;

typedef U8*         ptr8;
typedef U16*        ptr16;
typedef U32*        ptr32;
typedef U64*        ptr64;

//#define PARTITION_(X) X

#define CPL_DEF_TYPE_PTR_REF2_(type,name)\
  typedef type*           name##_ptr;\
  typedef type const*     name##_cptr;\
  typedef type volatile*  name##_vptr;\
  typedef type cpl_cv*    name##_cvptr;\
  typedef type&           name##_ref;\
  typedef type const&     name##_cref;\
  typedef type volatile&  name##_vref;\
  typedef type cpl_cv&    name##_cvref

#define CPL_DEF_TYPE_PTR_REF1_(type) CPL_DEF_TYPE_PTR_REF2_(type,type)

CPL_DEF_TYPE_PTR_REF1_(char);
CPL_DEF_TYPE_PTR_REF2_(unsigned char, u_char);
CPL_DEF_TYPE_PTR_REF1_(S8);
CPL_DEF_TYPE_PTR_REF1_(U8);
CPL_DEF_TYPE_PTR_REF1_(wchar_t);
CPL_DEF_TYPE_PTR_REF1_(short);
CPL_DEF_TYPE_PTR_REF2_(unsigned short, u_short);
CPL_DEF_TYPE_PTR_REF1_(S16);
CPL_DEF_TYPE_PTR_REF1_(U16);
CPL_DEF_TYPE_PTR_REF1_(int);
CPL_DEF_TYPE_PTR_REF2_(unsigned int, u_int);
CPL_DEF_TYPE_PTR_REF1_(S32);
CPL_DEF_TYPE_PTR_REF1_(U32);
CPL_DEF_TYPE_PTR_REF1_(long);
CPL_DEF_TYPE_PTR_REF2_(unsigned long, u_long);
CPL_DEF_TYPE_PTR_REF1_(S64);
CPL_DEF_TYPE_PTR_REF1_(U64);
CPL_DEF_TYPE_PTR_REF1_(float);
CPL_DEF_TYPE_PTR_REF1_(double);

typedef void*                 void_ptr;
typedef void const*           void_cptr;
typedef void volatile*        void_vptr;
typedef void volatile const*  void_cvptr;

template<class T> using ptr   = T*;
template<class T> using cptr  = T const*;
template<class T> using vptr  = T volatile*;
template<class T> using cvptr = T cpl_cv*;
template<class T> using ref   = T&;
template<class T> using cref  = T const&;
template<class T> using vref  = T volatile&;
template<class T> using cvref = T cpl_cv&;
template<class T> using rvref = T&&;



/// input parameter (auto reference)
template<class T> using _in = //cref<T>;
//  typename std::conditional
//  < std::is_scalar<T>::value || std::is_function<T>::value
//  , T const
//  , typename std::conditional
//    < (sizeof(T)<=sizeof(void*) && std::is_trivial<T>::value)
//    , T const
//    , T const&
//    >::type
//  >::type;
  typename std::conditional
    < std::is_rvalue_reference<T>::value
    , T&&
    , typename std::conditional
      < std::is_scalar<T>::value || std::is_function<T>::value
      , T const
      , T const&
      >::type
    >::type;

/// input pointer parameter
template<class T> using pin = cptr<T> const;


/// output reference parameter
template<class T> using rout = ref<T>;
/// output pointer parameter
template<class T> using pout = ptr<T> const;

/// in/out reference parameter
template<class T> using rio  = rout<T>;
/// in/out pointer parameter
template<class T> using pio  = pout<T>;

//#define CPL_TYPE_PTR_REF2_MEM(type)\
//  typedef type*          ptr;\
//  typedef type const*    cptr;\
//  typedef type volatile* vptr;\
//  typedef type cpl_cv*   cvptr;\
//  typedef type&          ref;\
//  typedef type const&    cref;\
//  typedef type volatile& vref;\
//  typedef type cpl_cv&   cvref

// UNICODE対応？
#ifdef CPL_UNICODE
  typedef wchar_t  str_type;
  typedef char     unstr_type;
#else
  typedef char     str_type;
  typedef wchar_t  unstr_type;
#endif
  typedef       str_type* str_ptr;
  typedef const str_type* str_cptr;
  typedef       unstr_type* unstr_ptr;
  typedef const unstr_type* unstr_cptr;

  using td_tstring = std::basic_string<str_type>;

// ナンバリング簡易宣言用マクロ
#define CPL_DECL_TYPE (type,name) type name
#define CPL_DECL_TYPENUM1(type,name) type name##1
#define CPL_DECL_TYPENUM2(type,name) type name##1, name##2
#define CPL_DECL_TYPENUM3(type,name) type name##1, name##2, name##3
#define CPL_DECL_TYPENUM4(type,name) CPL_DECL_TYPENUM3(type,name), name##4
#define CPL_DECL_TYPENUM5(type,name) CPL_DECL_TYPENUM4(type,name), name##5
#define CPL_DECL_TYPENUM6(type,name) CPL_DECL_TYPENUM5(type,name), name##6
#define CPL_DECL_TYPENUM7(type,name) CPL_DECL_TYPENUM6(type,name), name##7
#define CPL_DECL_TYPENUM8(type,name) CPL_DECL_TYPENUM7(type,name), name##8
// 接尾辞付
#define CPL_DECL_TYPENUM1E(type,name,end) type name##1##end
#define CPL_DECL_TYPENUM2E(type,name,end) type name##1##end, name##2##end
#define CPL_DECL_TYPENUM3E(type,name,end) type name##1##end, name##2##end, name##3##end
#define CPL_DECL_TYPENUM4E(type,name,end) CPL_DECL_TYPENUM3E(type,name,end), name##4##end
#define CPL_DECL_TYPENUM5E(type,name,end) CPL_DECL_TYPENUM4E(type,name,end), name##5##end
#define CPL_DECL_TYPENUM6E(type,name,end) CPL_DECL_TYPENUM5E(type,name,end), name##6##end
#define CPL_DECL_TYPENUM7E(type,name,end) CPL_DECL_TYPENUM6E(type,name,end), name##7##end
#define CPL_DECL_TYPENUM8E(type,name,end) CPL_DECL_TYPENUM7E(type,name,end), name##8##end



const float PI    = 3.141592f;
//const float toRAD = PI / 180.0f;
//inline float toRAD( float r ){ return r * PI / 180.0f; }
inline float toRAD( int   r ){ return r * PI / 180.0f; }
template<class T> inline T toRAD( T r ){ return r * PI / 180.0f; }
//const float toDEG = 180.0f / PI;
//inline float toDEG( float r ){ return r * 180.0f / PI; }
inline float toDEG( int   r ){ return r * 180.0f / PI; }
template<class T> inline T toDEG( T r ){ return r * 180.0f / PI; }

const U32 BIT0  = 1;
const U32 BIT1  = BIT0  << 1;
const U32 BIT2  = BIT1  << 1;
const U32 BIT3  = BIT2  << 1;
const U32 BIT4  = BIT3  << 1;
const U32 BIT5  = BIT4  << 1;
const U32 BIT6  = BIT5  << 1;
const U32 BIT7  = BIT6  << 1;
const U32 BIT8  = BIT7  << 1;
const U32 BIT9  = BIT8  << 1;
const U32 BIT10 = BIT9  << 1;
const U32 BIT11 = BIT10 << 1;
const U32 BIT12 = BIT11 << 1;
const U32 BIT13 = BIT12 << 1;
const U32 BIT14 = BIT13 << 1;
const U32 BIT15 = BIT14 << 1;
const U32 BIT16 = BIT15 << 1;
const U32 BIT17 = BIT16 << 1;
const U32 BIT18 = BIT17 << 1;
const U32 BIT19 = BIT18 << 1;
const U32 BIT20 = BIT19 << 1;
const U32 BIT21 = BIT20 << 1;
const U32 BIT22 = BIT21 << 1;
const U32 BIT23 = BIT22 << 1;
const U32 BIT24 = BIT23 << 1;
const U32 BIT25 = BIT24 << 1;
const U32 BIT26 = BIT25 << 1;
const U32 BIT27 = BIT26 << 1;
const U32 BIT28 = BIT27 << 1;
const U32 BIT29 = BIT28 << 1;
const U32 BIT30 = BIT29 << 1;
const U32 BIT31 = BIT30 << 1;

const U64 BIT32 = (U64)BIT31 << 1;
const U64 BIT33 = BIT32 << 1;
const U64 BIT34 = BIT33 << 1;
const U64 BIT35 = BIT34 << 1;
const U64 BIT36 = BIT35 << 1;
const U64 BIT37 = BIT36 << 1;
const U64 BIT38 = BIT37 << 1;
const U64 BIT39 = BIT38 << 1;
const U64 BIT40 = BIT39 << 1;
const U64 BIT41 = BIT40 << 1;
const U64 BIT42 = BIT41 << 1;
const U64 BIT43 = BIT42 << 1;
const U64 BIT44 = BIT43 << 1;
const U64 BIT45 = BIT44 << 1;
const U64 BIT46 = BIT45 << 1;
const U64 BIT47 = BIT46 << 1;
const U64 BIT48 = BIT47 << 1;
const U64 BIT49 = BIT48 << 1;
const U64 BIT50 = BIT49 << 1;
const U64 BIT51 = BIT50 << 1;
const U64 BIT52 = BIT51 << 1;
const U64 BIT53 = BIT52 << 1;
const U64 BIT54 = BIT53 << 1;
const U64 BIT55 = BIT54 << 1;
const U64 BIT56 = BIT55 << 1;
const U64 BIT57 = BIT56 << 1;
const U64 BIT58 = BIT57 << 1;
const U64 BIT59 = BIT58 << 1;
const U64 BIT60 = BIT59 << 1;
const U64 BIT61 = BIT60 << 1;
const U64 BIT62 = BIT61 << 1;
const U64 BIT63 = BIT62 << 1;

const int Ki =      1024;    // 2^10
const int Mi =      Ki * Ki; // 2^20
const int Gi =      Mi * Ki; // 2^30
const S64 Ti = (S64)Gi * Ki; // 2^40
const S64 Pi =      Ti * Ki; // 2^50
const S64 Ei =      Pi * Ki; // 2^60

constexpr unsigned long long int operator""_Ki( unsigned long long int val ){ return val * Ki; }
constexpr long double            operator""_Ki( long double            val ){ return val * Ki; }
constexpr unsigned long long int operator""_Mi( unsigned long long int val ){ return val * Mi; }
constexpr long double            operator""_Mi( long double            val ){ return val * Mi; }
constexpr unsigned long long int operator""_Gi( unsigned long long int val ){ return val * Gi; }
constexpr long double            operator""_Gi( long double            val ){ return val * Gi; }
constexpr unsigned long long int operator""_Ti( unsigned long long int val ){ return val * Ti; }
constexpr long double            operator""_Ti( long double            val ){ return val * Ti; }
constexpr unsigned long long int operator""_Pi( unsigned long long int val ){ return val * Pi; }
constexpr long double            operator""_Pi( long double            val ){ return val * Pi; }
constexpr unsigned long long int operator""_Ei( unsigned long long int val ){ return val * Ei; }
constexpr long double            operator""_Ei( long double            val ){ return val * Ei; }

// ARGB成分取得（主にWin32系。DirectXでは使えない。）
inline int GetAlpha( U32 color ){ return (color>>24) & 0xff; }
inline int GetA    ( U32 color ){ return (color>>24) & 0xff; }
inline int GetRed  ( U32 color ){ return (color>>16) & 0xff; }
inline int GetR    ( U32 color ){ return (color>>16) & 0xff; }
inline int GetGreen( U32 color ){ return (color>>8)  & 0xff; }
inline int GetG    ( U32 color ){ return (color>>8)  & 0xff; }
inline int GetBlue ( U32 color ){ return (color)     & 0xff; }
inline int GetB    ( U32 color ){ return (color)     & 0xff; }


// _____________________________________________________________________________
/// @brief 拡張enum
/// 
/// ※ このマクロを使う場合、任意の値から始まる連番でなければならない。
///
// *****************************************************************************
#define CPL_ENUM_EX( enumname, ... )\
  enum enumname { __VA_ARGS__, enumname##_END };                                \
  static char_cptr enumname##_NAME( int in_enum_value ){                        \
    static constexpr char_cptr str_buf_org = #__VA_ARGS__;                      \
    static size_t num = CPL::Core::strfunc<char>::str_count_(str_buf_org,",")+1;\
    static std::vector<char_cptr> strs( num, nullptr );                         \
    CPL_BLOCK_ONCE2                                                             \
    {                                                                           \
      static char tmp_str_buf[ sizeof(#__VA_ARGS__) ] = {};                     \
      auto   dest = tmp_str_buf;                                                \
      auto   addr_strs = &strs[0];                                              \
      for( auto src = str_buf_org; *src; ++src )                                \
      {                                                                         \
        if( *src == '=' ){ while( *src && *src != ',' ){ ++src; } }             \
        if( *addr_strs == nullptr ) *addr_strs = dest;                          \
        if( *src == ',' ) *dest++ = 0, ++addr_strs;                             \
        else if( *src  &&  *src != ' ' )                                        \
        {                                                                       \
          *dest++ = *src;                                                       \
        }                                                                       \
      }                                                                         \
      return true;                                                              \
    }();                                                                        \
    return strs[ in_enum_value - enumname##_END + num ];                        \
  }




// _____________________________________________________________________________
/// @brief 指定enum特殊化用構造体生成マクロ
///
// *****************************************************************************
#define CPL_ENUM_TYPE( enumname, classname, default_ )\
  struct classname\
  {\
    enumname value;\
    bool operator == ( classname const& val_ ) const { return (value == val_.value); }\
    bool operator == ( enumname         val_ ) const { return (value == val_); }\
    template<class T>\
    bool operator != ( T val_ ) const { return !(*this == val_); }\
    classname( classname const& val_ ) : value( val_.value ){}\
    classname( enumname val_ ) : value( val_ ){}\
    classname() : value( default_ ){}\
    classname& operator = ( classname const& val_ ){ value = val_.value; return *this; }\
  }

// _____________________________________________________________________________
/// @brief スコープ付きenumマクロ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_SCOPED_ENUM( enumname, type, ... )                            \
  struct enumname {                                                       \
    enum vals : type { __VA_ARGS__, enumname##_NUM };                     \
    type value;                                                           \
    enumname( enumname const& e ) : value( e.value ) {}                   \
    enumname( vals val ) : value( val ) {}                                \
    enumname( type val ) : value( val ) {}                                \
    enumname(){}                                                          \
    template<class T> enumname( T val ) : value(static_cast<type>(val)){} \
    operator type() const { return value; }                               \
    operator type&(){ return value; }                                     \
  }


// _____________________________________________________________________________
/// @brief なんも無し識別用
///
// *****************************************************************************
struct Nothing_ { constexpr Nothing_(){} };
constexpr Nothing_ kNOTHING;


// _____________________________________________________________________________
/// @brief デフォルト指定子？
///
// *****************************************************************************
struct Default_{ constexpr Default_(){}; };

constexpr Default_ kDEFAULT;

// _____________________________________________________________________________
/// @brief 初期化指定子みたいな。
///
// *****************************************************************************
struct Initialize_{ constexpr Initialize_(){}; };

constexpr Initialize_ kINITIALIZE;


// _____________________________________________________________________________
/// @brief 特定コンストラクタ用
///
// *****************************************************************************
struct InitializeVT_ { constexpr InitializeVT_(){}; };

constexpr InitializeVT_ kINITIALIZE_VT;


// _____________________________________________________________________________
/// @brief サイズ予約指定子
///
// *****************************************************************************
struct ReserveSize {
  size_t m_size;
  ReserveSize( size_t size ) : m_size(size) {}
};






template<class rep, class period> inline
void CPL_Sleep( std::chrono::duration<rep, period> in_time )
{
  std::this_thread::sleep_for( in_time );
}

inline void CPL_SleepAfterTimeSlice()
{
  std::this_thread::sleep_for( std::chrono::microseconds(0) );
}

inline void CPL_SleepNextTimeSlice()
{
  std::this_thread::sleep_for( std::chrono::microseconds(1) );
}

// ブレークマクロ
#ifdef CPL_DEBUG
  #define CPL_WAIT(o) \
  {\
    int zzz_flag_wait_loop_=(o);\
    if(zzz_flag_wait_loop_){\
      CPL_DBG_OUTPUT(SwS("CPL_WAIT! (When you escape, please set zzz_flag_wait_loop_ as false.)\n"));\
      while(zzz_flag_wait_loop_){ CPL_Sleep( std::chrono::milliseconds(100) ); }\
    }\
  }
//#ifdef CPL_PLATFORM_64
//# ifdef _MSC_VER
//#   define CPL_BREAK(o) if(o){ __debugbreak(); }
//# else
//#   define CPL_BREAK(o) CPL_WAIT(o)
//# endif
//#else
//# define CPL_BREAK(o) if(o){ __asm int 3 }
//#endif

# define CPL_BREAK(o) assert(!(o))

#else
# define CPL_WAIT(o)
# define CPL_BREAK(o)
#endif


void CPL_output( char_cptr    message );
void CPL_output( wchar_t_cptr message );


template<class... T_Params>
void CPL_OUTPUT_A_( char_cptr format, T_Params&&... args )
{
  char cpl_temp_str[1024];
  CPL_SPRINTF_A( cpl_temp_str, format, std::forward<T_Params>(args)... );
  CPL::CPL_output( cpl_temp_str );
}

template<class... T_Params>
void CPL_OUTPUT_W_( wchar_t_cptr format, T_Params&&... args )
{
  wchar_t cpl_temp_str[1024];
  CPL_SPRINTF_W( cpl_temp_str, format, std::forward<T_Params>(args)... );
  CPL::CPL_output( cpl_temp_str );
}

template<class... T_Params>
void CPL_OUTPUT_( char_cptr format, T_Params&&... args )
{
  CPL_OUTPUT_A_( format, std::forward<T_Params>(args)... );
}

template<class... T_Params>
void CPL_OUTPUT_( wchar_t_cptr format, T_Params&&... args )
{
  CPL_OUTPUT_W_( format, std::forward<T_Params>(args)... );
}


#ifdef CPL_UNICODE
//#define CPL_OUTPUT(format, ...) CPL::CPL_OUTPUT_W_( format, __VA_ARGS__ )
#define CPL_OUTPUT(...) CPL::CPL_OUTPUT_W_( __VA_ARGS__ )
#else
//#define CPL_OUTPUT(format, ...) CPL::CPL_OUTPUT_A_( format, __VA_ARGS__ )
#define CPL_OUTPUT(...) CPL::CPL_OUTPUT_A_( __VA_ARGS__ )
#endif
  
//#define CPL_OUTPUT_A(format, ...) CPL::CPL_OUTPUT_A_( format, __VA_ARGS__ )
//#define CPL_OUTPUT_W(format, ...) CPL::CPL_OUTPUT_W_( format, __VA_ARGS__ )
#define CPL_OUTPUT_A(...) CPL::CPL_OUTPUT_A_( __VA_ARGS__ )
#define CPL_OUTPUT_W(...) CPL::CPL_OUTPUT_W_( __VA_ARGS__ )


#ifdef CPL_DEBUG

  inline void CPL_output_debug( char_cptr    message ){ CPL_output( message ); }
  inline void CPL_output_debug( wchar_t_cptr message ){ CPL_output( message ); }


  // ( format, ... )
  #define CPL_DBG_OUTPUT(...) {\
    CPL::str_type cpl_temp_string0123456789_[1024];\
    CPL_SPRINTF(cpl_temp_string0123456789_, __VA_ARGS__);\
    CPL::CPL_output_debug(cpl_temp_string0123456789_);\
  }
 
  // ( format, ... ) 
  #define CPL_DBG_OUTPUT_A(...) {\
    char cpl_temp_string0123456789_[1024];\
    CPL_SPRINTF_A(cpl_temp_string0123456789_, __VA_ARGS__);\
    CPL::CPL_output_debug(cpl_temp_string0123456789_);\
  }
  
  // ( format, ... )
  #define CPL_DBG_OUTPUT_W(...) {\
    wchar_t cpl_temp_string0123456789_[1024];\
    CPL_SPRINTF_W(cpl_temp_string0123456789_, __VA_ARGS__);\
    CPL::CPL_output_debug(cpl_temp_string0123456789_);\
  }

  // (flag, format, ... )
  #define CPL_DBG_OUTPUT_IF(flag, ...)\
    if(flag) CPL_DBG_OUTPUT(__VA_ARGS__)

  // (flag, format, ... )
  #define CPL_DBG_OUTPUT_RETURN_IF(flag, ...)\
    if(flag){ CPL_DBG_OUTPUT(__VA_ARGS__) return; }

  // (flag, val, format, ... )
  #define CPL_DBG_OUTPUT_RETURN_VALUE_IF(flag, val, ...)\
    if(flag){ CPL_DBG_OUTPUT(__VA_ARGS__) return val; }
    
#else  // not CPL_DEBUG

  inline void CPL_output_debug( char_cptr message ){}
  inline void CPL_output_debug( wchar_t const* message ){}

  #define CPL_DBG_OUTPUT(format, ...) {}
  #define CPL_DBG_OUTPUT_A(format, ...) {}
  #define CPL_DBG_OUTPUT_W(format, ...) {}
  #define CPL_DBG_OUTPUT_IF(flag, format, ...) {}
  #define CPL_DBG_OUTPUT_RETURN_IF(flag, format, ...) if(flag){ return; }
  #define CPL_DBG_OUTPUT_RETURN_VALUE_IF(flag, val, format, ...) if(flag){ return val; }

#endif // CPL_DEBUG



// _____________________________________________________________________________
/// @brief 無効インデックス判定
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
inline bool FAILED_INDEX( S8  idx ){ return (idx < 0); }
inline bool FAILED_INDEX( S16 idx ){ return (idx < 0); }
inline bool FAILED_INDEX( S32 idx ){ return (idx < 0); }
inline bool FAILED_INDEX( S64 idx ){ return (idx < 0L); }
inline bool FAILED_INDEX( U8  idx ){ return (idx == 0xFF); }
inline bool FAILED_INDEX( U16 idx ){ return (idx == 0xFFFF); }
inline bool FAILED_INDEX( U32 idx ){ return (idx == 0xFFFFFFFF); }
inline bool FAILED_INDEX( U64 idx ){ return (idx == 0xFFFFFFFFFFFFFFFFUL); }


// _____________________________________________________________________________
/// @brief 無効インデックス判定（最大値判定有り）
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
inline bool FAILED_INDEX( S8  idx, S8  idx_max ){ return (idx < 0  ||  idx > idx_max); }
inline bool FAILED_INDEX( S16 idx, S16 idx_max ){ return (idx < 0  ||  idx > idx_max); }
inline bool FAILED_INDEX( S32 idx, S32 idx_max ){ return (idx < 0  ||  idx > idx_max); }
inline bool FAILED_INDEX( S64 idx, S64 idx_max ){ return (idx < 0L ||  idx > idx_max); }
inline bool FAILED_INDEX( U8  idx, U8  idx_max ){ return (idx > idx_max); }
inline bool FAILED_INDEX( U16 idx, U16 idx_max ){ return (idx > idx_max); }
inline bool FAILED_INDEX( U32 idx, U32 idx_max ){ return (idx > idx_max); }
inline bool FAILED_INDEX( U64 idx, U64 idx_max ){ return (idx > idx_max); }



// _____________________________________________________________________________
/// @brief 配列サイズの取得
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_ARRAY_NUM(arr) (sizeof(arr)/sizeof(arr[0]))



// _____________________________________________________________________________
/// @brief 配列の単純初期化付き定義
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CPL_ARRAY_DEFINIT( type, name, size, init )\
  type name[ size ];\
  for( int i = 0; i < size; ++i ){ name[i] = init; }


// _____________________________________________________________________________
/// @brief 引数の個数を取得。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class... T_Params> inline
constexpr int GetArgsNum( T_Params&&... args )
{
  return sizeof...( args );
}



// _____________________________________________________________________________
/// @brief ２乗の値を取得
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
T_Type Squ( T_Type o ){ return o*o; }



// _____________________________________________________________________________
/// @brief 絶対値を取得
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
T_Type Abs( T_Type o ){ return o > 0 ? o : -o; }


// _____________________________________________________________________________
/// @brief 符号を取得
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
int Sign( T_Type o ){ return o == 0 ? 0 : ((o > 0) ? 1 : -1); }


// _____________________________________________________________________________
/// @brief 交換
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T0, class T1> inline
void Swap( T0& a, T1& b )
{
  T0 t = a;
  a = static_cast<T0>(b);
  b = static_cast<T1>(t);
}


// _____________________________________________________________________________
/// @brief 交換マクロ（インライン関数で指定できない場合）
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define MSwap( type, a, b ) \
do {\
  type t = a;\
  b = a;\
  a = t;\
} while(1)



// _____________________________________________________________________________
/// @brief 指定したサイズの切捨てアライメントサイズを取得。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T> inline
constexpr T AlignLow( T in_value, T in_align )
{
  return in_value / in_align * in_align;
}


// _____________________________________________________________________________
/// @brief 指定したサイズの切り上げアライメントサイズを取得。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T> inline
constexpr T AlignHigh( T in_value, T in_align )
{
  return (in_value + in_align - 1) / in_align * in_align;
}




// _____________________________________________________________________________
/// @brief 最大値を取得。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
T_Type Max( T_Type const& a, T_Type const& b )
{
  return a < b ? b : a;
}

// _____________________________________________________________________________
/// @brief 最大値を取得。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type, class... T_Params> inline
T_Type Max( T_Type const& a, T_Type const& b, T_Params const&... args )
{
  return Max( a < b ? b : a, args... );
}

// _____________________________________________________________________________
/// @brief 最大値を取得。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
T_Type Max( T_Type cpl_cv& a, T_Type cpl_cv& b )
{
  return a < b ? b : a;
}

// _____________________________________________________________________________
/// @brief 最大値を取得。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type, class... T_Params> inline
T_Type Max( T_Type cpl_cv& a, T_Type cpl_cv& b, T_Params cpl_cv&... args )
{
  return Max( a < b ? b : a, args... );
}



// _____________________________________________________________________________
/// @brief 最小値を取得。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
T_Type Min( T_Type const& a, T_Type const& b )
{
  return a < b ? a : b;
}

// _____________________________________________________________________________
/// @brief 最小値を取得。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type, class... T_Params> inline
T_Type Min( T_Type const& a, T_Type const& b, T_Params const&... args )
{
  return Min( a < b ? a : b, args... );
}

// _____________________________________________________________________________
/// @brief 最小値を取得。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
T_Type Min( T_Type cpl_cv& a, T_Type cpl_cv& b )
{
  return a < b ? a : b;
}

// _____________________________________________________________________________
/// @brief 最小値を取得。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type, class... T_Params> inline
T_Type Min( T_Type cpl_cv& a, T_Type cpl_cv& b, T_Params cpl_cv&... args )
{
  return Min( a < b ? a : b, args... );
}




// _____________________________________________________________________________
/// @brief 数値が格納されたテーブルから最大値を検索する
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
const T_Type& MaxTbl( const T_Type* in_ptr_tbl, int in_num )
{
  const T_Type* ptr_end = in_ptr_tbl + in_num;
  const T_Type* ptr_ret = in_ptr_tbl;
  while( ++in_ptr_tbl < ptr_end )
  {
    if( *ptr_ret < *in_ptr_tbl )
    {
      ptr_ret = in_ptr_tbl;
    }
  }
  return *ptr_ret;
}



// _____________________________________________________________________________
/// @brief 数値が格納されたテーブルから最大値を検索する
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
const T_Type& MinTbl( const T_Type* in_ptr_tbl, int in_num )
{
  const T_Type* ptr_end = in_ptr_tbl + in_num;
  const T_Type* ptr_ret = in_ptr_tbl;
  while( ++in_ptr_tbl < ptr_end )
  {
    if( *ptr_ret > *in_ptr_tbl )
    {
      ptr_ret = in_ptr_tbl;
    }
  }
  return *ptr_ret;
}



// Doxygenにおけるテンプレートの解析ミスを回避するためのマクロ
//#define CPL_DEF_DOXYGEN_HELPER_TEMPLATE_CHECK_MAX_(T0,T1) (sizeof(T0)>=sizeof(T1))
//#define CPL_DEF_DOXYGEN_HELPER_TEMPLATE_CHECK_MIN_(T0,T1) (sizeof(T0)<=sizeof(T1))

// _____________________________________________________________________________
/// @brief 最大型サイズ取得クラス
/// 
/// 複数の型から最大サイズをメンバ[size]に設定。\n
/// 複数の型から最大サイズの型をメンバ[type]に設定。（優先順位は前方が高）
///
// *****************************************************************************
template<class... T_Params>
struct TypeMax {};

/// @cond
// _____________________________________________________________________________
/// @brief 最大型サイズ取得クラス
/// 
/// 複数の型から最大サイズをメンバ[size]に設定。\n
/// 複数の型から最大サイズの型をメンバ[type]に設定。（優先順位は前方が高）
///
// *****************************************************************************
template<class T0, class T1, class... T_Params>
struct TypeMax<T0, T1, T_Params...>
  : TypeMax
    < typename std::conditional
      < (sizeof(T0)>=sizeof(T1))
      , T0
      , T1
      >::type,
      T_Params...>
{};

// _____________________________________________________________________________
/// @brief TypeMax 終了条件。
///
// *****************************************************************************
template<class T0>
struct TypeMax<T0>
{
  static const int size = sizeof(T0);
  typedef T0 type;
};
/// @endcond


// _____________________________________________________________________________
/// @brief 最小型サイズ取得クラス
/// 
/// 複数の型から最小サイズをメンバ[size]に設定。\n
/// 複数の型から最小サイズの型をメンバ[type]に設定。（優先順位は前方が高）
///
// *****************************************************************************
template<class... T_Params>
struct TypeMin {};

/// @cond
// _____________________________________________________________________________
/// @brief 最小型サイズ取得クラス
/// 
/// 複数の型から最小サイズをメンバ[size]に設定。\n
/// 複数の型から最小サイズの型をメンバ[type]に設定。（優先順位は前方が高）
///
// *****************************************************************************
template<class T0, class T1, class... T_Params>
struct TypeMin<T0, T1, T_Params...>
  : TypeMin
    < typename std::conditional
      < (sizeof(T0)<=sizeof(T1))
      , T0
      , T1
      >::type,
      T_Params...>
{
};

// _____________________________________________________________________________
/// @brief TypeMin 終了条件。
///
// *****************************************************************************
template<class T0>
struct TypeMin<T0>
{
  static const int size = sizeof(T0);
  typedef T0 type;
};
/// @endcond



// _____________________________________________________________________________
/// @brief 指定した数値に対し、最小および最大の補正値を取得。
///
/// @param[in] in_value : クランプする対象の値。
/// @param[in] in_min   : 最小値。
/// @param[in] in_max   : 最大値。
///
/// @return クランプ後の値。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
T_Type Clamp( cref<T_Type> in_value, _in<T_Type> in_min, _in<T_Type> in_max )
{
  return Max(in_min,Min(in_value,in_max));
}


// _____________________________________________________________________________
/// @brief 範囲検査。
///
/// @param[in] in_value : クランプする対象の値。
/// @param[in] in_min   : 最小値。
/// @param[in] in_max   : 最大値。
///
/// @retval false : 範囲内（min <= value <= max）
/// @retval true  : 範囲外
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
bool Limit( cref<T_Type> in_value, _in<T_Type> in_min, _in<T_Type> in_max )
{
  return ( in_value < in_min  ||  in_max < in_value );
}



// _____________________________________________________________________________
/// @brief ２つの値の符号不一致チェック。
///
/// @param[in] in_value0 : １つめの値。
/// @param[in] in_value1 : ２つめの値。
///
/// @retval true  : 符号が不一致。
/// @retval false : 符号が一致。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
bool DisagreeSign( _in<T_Type> in_value0, _in<T_Type> in_value1 )
{
  return ((in_value0 < 0) ^ (in_value1 < 0));
}



// _____________________________________________________________________________
/// @brief ２つの値の符号一致チェック。
///
/// @param[in] in_value0 : １つめの値。
/// @param[in] in_value1 : ２つめの値。
///
/// @retval true  : 符号が一致。
/// @retval false : 符号が不一致。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
bool SameSign( _in<T_Type> in_value0, _in<T_Type> in_value1 )
{
  return !DisagreeSign( in_value0, in_value1 );
}


// _____________________________________________________________________________
/// @brief ビットムーブ。
///
/// b から a にムーブ。
///
/// @param[out]    a : 移動先
/// @param[in,out] b : 移動元（bはクリアされる）
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
void BitMove( T_Type& a, T_Type& b )
{
  memcpy( &a, &b, sizeof(T_Type) );
  memset( &b, 0, sizeof(T_Type) );
}

// _____________________________________________________________________________
/// @brief ビットムーブ。
///
/// b から a にムーブ。
///
/// @param[out]    a : 移動先
/// @param[in,out] b : 移動元（bはクリアされる）
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
void BitMove( T_Type& a, T_Type&& b )
{
  memcpy( &a, &b, sizeof(T_Type) );
  memset( &b, 0, sizeof(T_Type) );
}


const int kPRIORITY_HIGHEST = 7;  ///< 最高優先レベル。
const int kPRIORITY_LOWEST  = -7; ///< 最低優先レベル。
// _____________________________________________________________________________
/// @brief 優先順位クラス
///
/// @par Example
/// struct A { A( int a ){} };                                         \n
/// struct B { B( int b ){} };                                         \n
/// void func( A a, Priority<1>* = UsePriority ); // 優先ランクが高い。\n
/// void func( B b, Priority<0>* = UsePriority );                      \n
/// ...                                                                \n
/// void main(){                                                       \n
/// 　func( 0 ); // A側が呼ばれる。                                    \n
/// }
// *****************************************************************************
template<int level>
class Priority : public Priority<level-1> {};
template<>
class Priority<kPRIORITY_LOWEST>{};

Priority<kPRIORITY_HIGHEST>* const UsePriority = nullptr;



// _____________________________________________________________________________
/// @brief 数値->型 識別用
// *****************************************************************************
template<int signature>
class ValueType
{
public:
  static constexpr int value = signature;

  ValueType() = default;
};


// _____________________________________________________________________________
/// @brief 型タプル
///
/// ※ std::tupleは実体を持てる仕様のため、指定できない型がある。
///    そのためTupleTypeを用意している。
///
// *****************************************************************************
template<class... T_Params>
class TupleType
{
private:
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<int N, class... T_Params>
  struct detail_ {};

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<int N, class T, class... T_Params>
  struct detail_<N, T, T_Params...>
    : detail_<N + 1, T_Params...>
  {
    typedef T type;
  };
  //
  template<int N, class T>
  struct detail_<N, T>
  {
    static const int value = N + 1;
    typedef T type;
  };

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<int N, class... X, class... T_Params>
  struct detail_<N, TupleType<X...>, T_Params...>
    : detail_
      < N + TupleType<X...>::all_num
      , T_Params... >
  {
    typedef TupleType<X...> type;
  };
  //
  template<int N, class... X>
  struct detail_<N, TupleType<X...>>
  {
      static const int value = N + TupleType<X...>::all_num;
    typedef TupleType<X...> type;
  };

public:
  static const int num     = sizeof...(T_Params);
  static const int all_num = detail_<0, T_Params...>::value;

  // _____________________________________________________________________________
  /// @brief N番目の型をtypeに設定。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<int T_Idx>
  struct Get
  {
  private:
    template<int idx_, class type_, class... params_>
    struct detail_ : detail_< idx_-1, params_...> {};

    // 終了条件。
    template<class type_, class... params_>
    struct detail_<0, type_, params_...>
    {
      typedef type_ type;
    };

    // インデックスが不正。
    template<int idx_, class type_>
    class detail_<idx_, type_>{};
  public:
    typedef typename detail_<T_Idx, T_Params...>::type type;
  };

  // _____________________________________________________________________________
  /// @brief 子供階層を含む、全ての型からN番目の型をtypeに設定。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<int T_Idx>
  struct GetAll
  {
    typedef typename detail_<T_Idx, T_Params...>::type type;
  };
};



// _____________________________________________________________________________
/// @brief 定数のタプル化クラス
///
/// @tparam T_Type   : 定数の型。
/// @tparam T_Values : 定数リストを指定する。
/// @par Example
/// auto x = TupleConstant<int, 1,2,3,5,7>::Get<3>::value; // x==5となる。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type, T_Type... T_Values>
class TupleConstant
{
  typedef T_Type type;  ///< 指定されている型。
  static const int num = sizeof...(T_Values); ///< 指定されている要素数。
public:
  template<int T_Idx>
  class Get
  {
    template<int idx_, T_Type val_, T_Type... values_>
    struct detail_ : detail_< idx_-1, values_...> {};

    template<int val_, T_Type... values_>
    struct detail_<0, val_, values_...>
    {
      static const T_Type value = val_;
    };

    template<int idx_, T_Type val_>
    class detail_<idx_, val_>{}; // インデックスが不正。
  public:
    static const type value = detail_< T_Idx, T_Values...>::value;
  };
};


// _____________________________________________________________________________
/// @brief ポインタ変数のタプル化クラス
///
/// @tparam T_Type   : 最初のポインタの型。
/// @tparam T_Values : 続くポインタの型。
/// @par Example
/// int a;
/// float b;
/// double c;
/// auto plist = TuplePointer<int,float,double>( &a, &b, &c );
// *****************************************************************************
template<class T_Type, class... T_Params>
class TuplePointer
  : public TuplePointer<T_Params...>
{
  using td_type_base = TuplePointer<T_Params...>;
  using td_type_ptr  = std::add_pointer_t<std::remove_reference_t<T_Type>>;
public:
  template<class... Ts>
  TuplePointer( T_Type& obj0, Ts&&... objects )
    : td_type_base( objects... )
    , m_ptr_obj( &obj0 )
  {}

  constexpr static int GetNum(){ return sizeof...(T_Params) + 1; }

protected:
  td_type_ptr m_ptr_obj;
};

// _____________________________________________________________________________
template<class T_Type>
class TuplePointer<T_Type>
{
  using td_type_this = TuplePointer<T_Type>;
  using td_type_ptr  = std::add_pointer_t<T_Type>;
  friend td_type_this;
protected:
  TuplePointer( td_type_ptr p )
    : m_ptr_obj( p )
  {}

  ref<td_type_this> operator = ( cref<td_type_this> in_tuple_p )
  {
    m_ptr_obj = in_tuple_p.m_ptr_obj;
    return *this;
  }

  constexpr static int GetNum(){ return 1; }

protected:
  td_type_ptr m_ptr_obj;
};


// _____________________________________________________________________________
/// @brief ポインタ組生成用ヘルパ関数
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T, class... T_Params>
TuplePointer<T, T_Params...> MakeTuplePointer( T p, T_Params&&... in_args )
{
  return std::move( TuplePointer<T_Params...>(p, in_args...) );
}




// _____________________________________________________________________________
/// 引数属性サポート型
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
namespace sem {
  struct _argSemantics{};
  template<class T>
  struct _argVal : _argSemantics
  {
    T val;
    _argVal( T val_ ) : val(val_){}
    operator T&      ()       { return val; }
    operator T const&() const { return val; }
  };

  #define CPL_DEF_RETYPE(basetype,newtype)\
    class newtype : public basetype { using _base=basetype; using _base::_base; };

  #define CPL_DEF_RETYPE_T(basetype,newtype)\
    template<class T>\
    class newtype : public basetype<T>{ using _base=basetype<T>; using _base::_base; };

  #define CPL_DEF_ARG_VALTYPE_RENAME_T(name)\
    CPL_DEF_RETYPE_T(_argVal,name)

  #define CPL_DEF_ARG_SEMANTICS(name)\
    CPL_DEF_ARG_VALTYPE_RENAME_T( CPL_PAIR(t_,name) )\
    template<class T> inline auto name(cref<T> x){ return CPL_PAIR(t_,name)<T>(x); }

  //#define CPL_DEF_ARG_SEMANTICS_T(name)\
  //  CPL_DEF_ARG_VALTYPE_RENAME_T( CPL_PAIR(t_,name) )\
  //  template<class T, class... Ts> inline\
  //  CPL_PAIR(t_,name)<T> name(Ts&&... args){ return CPL_PAIR(t_,name)<T>(args...); }

  #define CPL_DEF_MEMBER_SETUP(memtype, memname, semantics)\
    memtype memname;\
    template<class T> void setParam_( semantics<T>&& data ){ memname = data; }

  CPL_DEF_ARG_SEMANTICS( X )
  CPL_DEF_ARG_SEMANTICS( Y )
  CPL_DEF_ARG_SEMANTICS( Z )
  CPL_DEF_ARG_SEMANTICS( W )
  CPL_DEF_ARG_SEMANTICS( A )
  CPL_DEF_ARG_SEMANTICS( R )
  CPL_DEF_ARG_SEMANTICS( G )
  CPL_DEF_ARG_SEMANTICS( B )
  CPL_DEF_ARG_SEMANTICS( Width  )
  CPL_DEF_ARG_SEMANTICS( Height )
  CPL_DEF_ARG_SEMANTICS( Left   )
  CPL_DEF_ARG_SEMANTICS( Right  )
  CPL_DEF_ARG_SEMANTICS( Top    )
  CPL_DEF_ARG_SEMANTICS( Bottom )
  CPL_DEF_ARG_SEMANTICS( ID     )
  CPL_DEF_ARG_SEMANTICS( UserID )
  CPL_DEF_ARG_SEMANTICS( Min )
  CPL_DEF_ARG_SEMANTICS( Max )
  CPL_DEF_ARG_SEMANTICS( No )
  CPL_DEF_ARG_SEMANTICS( Index )
  CPL_DEF_ARG_SEMANTICS( Rect )
  CPL_DEF_ARG_SEMANTICS( Position )
  CPL_DEF_ARG_SEMANTICS( Size )
  CPL_DEF_ARG_SEMANTICS( Scale )
  CPL_DEF_ARG_SEMANTICS( Center )
  CPL_DEF_ARG_SEMANTICS( Rotate )
  CPL_DEF_ARG_SEMANTICS( Depth )
  CPL_DEF_ARG_SEMANTICS( Color )
  CPL_DEF_ARG_SEMANTICS( Alpha )

  #define CPL_DEF_ARG_SEMANTICS_FOR_STRING(name)\
    CPL_DEF_ARG_VALTYPE_RENAME_T(t_##name)\
    inline t_##name<std::string>  name(cref<std::string> s){ return t_##name<std::string>(s); }\
    inline t_##name<std::wstring> name(cref<std::wstring> s){ return t_##name<std::wstring>(s); }\
    inline t_##name<std::string>  name(char_cptr s){ return t_##name<std::string>(s); }\
    inline t_##name<std::wstring> name(wchar_t_cptr s){ return t_##name<std::wstring>(s); }

  CPL_DEF_ARG_SEMANTICS_FOR_STRING( String )
  CPL_DEF_ARG_SEMANTICS_FOR_STRING( Message )
  CPL_DEF_ARG_SEMANTICS_FOR_STRING( Name )
  CPL_DEF_ARG_SEMANTICS_FOR_STRING( Title )
  CPL_DEF_ARG_SEMANTICS_FOR_STRING( StrID )
  CPL_DEF_ARG_SEMANTICS_FOR_STRING( Label )

  //using _arg_S8  = _argVal<S8>;
  //using _arg_S16 = _argVal<S16>;
  //using _arg_S32 = _argVal<S32>;
  //using _arg_S64 = _argVal<S64>;
  //using _arg_U8  = _argVal<U8>;
  //using _arg_U16 = _argVal<U16>;
  //using _arg_U32 = _argVal<U32>;
  //using _arg_U64 = _argVal<U64>;
  //using _arg_Float   = _argVal<float>;
  //using _arg_Double  = _argVal<double>;
  //using _arg_StdStr  = _argVal<std::string>;
  //using _arg_StdWStr = _argVal<std::wstring>;
  //
  //#define CPL_DEF_ARG_COMVERT(basetype,newtype,type,name)\
  //  CPL_DEF_RETYPE(basetype, arg_##newtype)\
  //  inline arg_##newtype name(type x){ return arg_##newtype(x); }
  //#define CPL_DEF_ARG_TYPES_SINT(basetypeT,name)\
  //  CPL_DEF_ARG_COMVERT(baseT<S8> ,name##S8, S8, name)\
  //  CPL_DEF_ARG_COMVERT(baseT<S16>,name##S16,S16,name)\
  //  CPL_DEF_ARG_COMVERT(baseT<S32>,name##S32,S32,name)\
  //  CPL_DEF_ARG_COMVERT(baseT<S64>,name##S64,S64,name)
  //
  //#define CPL_DEF_ARG_TYPES_UINT(name)\
  //  CPL_DEF_ARG_COMVERT(_arg_U8, name##U8, U8, name)\
  //  CPL_DEF_ARG_COMVERT(_arg_U16,name##U16,U16,name)\
  //  CPL_DEF_ARG_COMVERT(_arg_U32,name##U32,U32,name)\
  //  CPL_DEF_ARG_COMVERT(_arg_U64,name##U64,U64,name)
  //
  //#define CPL_DEF_ARG_TYPES_FLOAT(name)\
  //  CPL_DEF_ARG_COMVERT(_arg_Float ,name##Float, float ,name)\
  //  CPL_DEF_ARG_COMVERT(_arg_Double,name##Double, double,name)
  //
  //#define CPL_DEF_ARG_TYPES_VALUES(name)\
  //  CPL_DEF_ARG_TYPES_SINT(name)\
  //  CPL_DEF_ARG_TYPES_UINT(name)\
  //  CPL_DEF_ARG_TYPES_FLOAT(name)
  //  
  //CPL_DEF_ARG_TYPES_VALUES(X_)
  //CPL_DEF_ARG_TYPES_VALUES(Y_)
  //CPL_DEF_ARG_TYPES_VALUES(Z_)
  //CPL_DEF_ARG_TYPES_VALUES(A_)
  //CPL_DEF_ARG_TYPES_VALUES(R_)
  //CPL_DEF_ARG_TYPES_VALUES(G_)
  //CPL_DEF_ARG_TYPES_VALUES(B_)
  //CPL_DEF_ARG_TYPES_VALUES(Width_)
  //CPL_DEF_ARG_TYPES_VALUES(Height_)
  //CPL_DEF_ARG_TYPES_VALUES(Left_)
  //CPL_DEF_ARG_TYPES_VALUES(Right_)
  //CPL_DEF_ARG_TYPES_VALUES(Top_)
  //CPL_DEF_ARG_TYPES_VALUES(Bottom_)
  //CPL_DEF_ARG_TYPES_VALUES(ID_)
  //CPL_DEF_ARG_COMVERT(_arg_StdStr ,ID_A_    ,std::string ,ID_     )
  //CPL_DEF_ARG_COMVERT(_arg_StdWStr,ID_W_    ,std::wstring,ID_     )
  //CPL_DEF_ARG_COMVERT(_arg_StdStr ,StrA_    ,std::string ,Str_    )
  //CPL_DEF_ARG_COMVERT(_arg_StdWStr,StrW_    ,std::wstring,Str_    )
  //CPL_DEF_ARG_COMVERT(_arg_StdStr ,NameA_   ,std::string ,Name_   )
  //CPL_DEF_ARG_COMVERT(_arg_StdWStr,NameW_   ,std::wstring,Name_   )
  //CPL_DEF_ARG_COMVERT(_arg_StdStr ,TitleA_  ,std::string ,Title_  )
  //CPL_DEF_ARG_COMVERT(_arg_StdWStr,TitleW_  ,std::wstring,Title_  )
  //CPL_DEF_ARG_COMVERT(_arg_StdStr ,MessageA_,std::string ,Message_)
  //CPL_DEF_ARG_COMVERT(_arg_StdWStr,MessageW_,std::wstring,Message_)
} // namespace sem


} // namespace CPL


