📝
scoped enum用オーバーロード関数
はじめに
今回開発時にログ用のオーバーロード関数を作成していました.しかし,scopedenum で定義した型用の関数を全種分定義するわけにもいかず,どうにかならいなかと思って調べた結果の備忘録です.
サンプルコード
main.cpp
#include <stdio.h>
#include <vector>
// retrun macro
#define RET_MACRO(retData){\
print(__func__, retData);\
return retData;\
}
#define RET_VOICE_MACRO(){\
print(__func__);\
return;\
}
enum class Hoge
{
A = 0,
B,
C,
};
// scoped enum
template<typename T>
void print(const char* funcName
, T num
, typename std::enable_if<std::is_enum<T>::value, std::nullptr_t>::type = nullptr)
{
printf("%-20s : %d\n", funcName, num);
}
// double
void print(const char* funcName, double num)
{
printf("%-20s : %f\n", funcName, num);
}
// int
void print(const char* funcName, int num)
{
printf("%-20s : %d\n", funcName, num);
}
// vector
template<typename T>
struct is_vector : std::false_type {};
template<typename T>
struct is_vector<std::vector<T>> : std::true_type {};
template<typename T>
void print(const char* funcName
, T num
, typename std::enable_if<is_vector<T>::value, std::nullptr_t>::type = nullptr)
{
printf("%-20s : vec\n", funcName);
}
// other
void print(const char* funcName, ...)
{
printf("%-20s : --\n", funcName);
}
// return int
int retIntFuc()
{
RET_MACRO(5);
}
// return double
double retDoubleFuc()
{
RET_MACRO(0.5);
}
// return scoped enum
Hoge retScopedEnumFuc()
{
RET_MACRO(Hoge::B);
}
// return vector
std::vector<int> retVectorFunc()
{
std::vector<int> vec;
RET_MACRO(vec);
}
// retrun other
struct Othr
{
int a;
int b;
};
Othr retOtherFunc()
{
Othr other = {};
RET_MACRO(other);
}
// retrun other
void retVoidFunc()
{
RET_VOICE_MACRO();
}
int main()
{
retIntFuc();
retDoubleFuc();
retScopedEnumFuc();
retVectorFunc();
retOtherFunc();
retVoidFunc();
return 0;
}
// return double
double retDoubleFuc()
{
RET_MACRO(0.5);
}
// return scoped enum
Hoge retScopedEnumFuc()
{
RET_MACRO(Hoge::B);
}
// return vector
std::vector<int> retVectorFunc()
{
std::vector<int> vec;
RET_MACRO(vec);
}
// retrun other
struct Othr
{
int a;
int b;
};
Othr retOtherFunc()
{
Othr other = {};
RET_MACRO(other);
}
// retrun other
void retVoidFunc()
{
RET_VOICE_MACRO();
}
int main()
{
retIntFuc();
retDoubleFuc();
retScopedEnumFuc();
retVectorFunc();
retOtherFunc();
retVoidFunc();
return 0;
}
実行結果
retIntFuc : 5
retDoubleFuc : 0.500000
retScopedEnumFuc : 1
retVectorFunc : vec
retOtherFunc : --
retVoidFunc : --
解説
23 ~ 51 行目までの print 関数がログ用の関数で,今回の肝となるのが 22 ~ 26 行目の scopedenum 用の print 関数です.
大まかな流れは以下通りです.
・渡された引数の型が enum か否かを「std::is_enum」にて判定を行います.enum であれば true を返す.
・「std::enable_if」は「is_enum」が true となれば enbale_if は「std::nullptr_t」型として実態化.
・これにより enum 以外の場合 SFINAE によって,オーバーロード解決の候補から外され,enum のときに実行される関数ができる.
私自身少しふわっとした理解なので,間違い等あれば指摘していただけるとありがたいです.
また,vector は後で必要になったので,参考文献 4 を参考にメタ関数等作成しました.
参考文献
1.enable_if - cpprefjp - C++日本語リファレンス
2.enable_if クラス
3.【C++ Advent Calendar 2016 22 日目】C++ で enable_if を使うコードのベストプラクティス
4.C++メタ関数のまとめ
Discussion