C++
C++11
テンプレートメタプログラミング
SFINAE
VisualStudio2015

コードだけバーン

うまく解説できる気はしません・・・。

要はfuncという名前のオーバーロードメソッドを実装しているかを検査し、実装していなければ呼び出しが起きません。これはfuncというメソッドがfunc(int, int);でもfunc(string);でも実装しているものとして呼び出されます。

これの良いところは呼び出し側はfunc(int, int);としてもfunc(string);としてもfunc(string, const UserClass&);としても関係のあるクラスにさえ実装しておけばOKというところです。

has_func.h
////////////////////////////////////////////////////////////////////////////////
//
// Light Wings GameProject
//
// (C) 2009 Light Wings GameProject.
//
// https://github.com/LightWings-GameProject
//
////////////////////////////////////////////////////////////////////////////////

// funcオーバーロード関数を定義されたクラスであるかどうかを確認する
template < typename T, typename ...Args >
struct has_func
{
private:
    template < typename U >
    static auto Check(U& x, Args&& ...args)->decltype(x.func(std::declval<Args>()...), std::true_type{});
    static std::false_type Check(...);

public:
    static const bool value = decltype(Check(std::declval<T>(), std::declval<Args>()...))::value;
};

// funcオーバーロード関数が定義された時だけ呼び出す
template < typename T, typename ...Args>
auto CallFuncIfExists(T&& instance, Args&& ...args)->typename std::enable_if<has_func<T, Args...>::value>::type
{
    instance.func(std::forward<Args>(args)...);
}

// 未定義の時は何もしない
template < typename T, typename ...Args>
auto CallFuncIfExists(T&& instance, Args&& ...args)->typename std::enable_if<!has_func<T, Args...>::value>::type
{
    // Do Nothing...
}
sample.cpp
CallFuncIfExists(instance, std::forward<Args>(args)...);
The MIT License (MIT)
Copyright (C) 2009 Light Wings GameProject.

確認環境

Visual Studio 2015で動作確認。
UE4でも動く。Windows(Steam)、PS4、Xbox Oneでもコンパイル通って動く。
何か問題起きたら対処は出来ないかもしれないけど、このコードの利用者は嬉しいかもしれません。

参考

decltypeとSFINAEによるオーバーロード条件分岐
C++メタ関数のまとめ
std::enable_ifを使ってオーバーロードする時、enablerを使う?