LoginSignup
0
0

More than 5 years have passed since last update.

scoped enum用オーバーロード関数

Last updated at Posted at 2018-09-09

はじめに

今回開発時にログ用のオーバーロード関数を作成していました.しかし,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++メタ関数のまとめ

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0