私のコードでは、テンプレートに指定された型がポインターであるかどうかをテストする必要があります-それがスマートかどうか。ブーストによると、それを行うための信頼できる一般的な方法はありません(ここを参照)-またはありますか?
これまでのところ、私は次のことを確認します。
- A:
T
に変換できますvoid*
か? - B:方法は
T
ありget()
ますか? - C:
T
というタイプはありelement_type
ますか? - D:
get()
戻りelement_type*
ますか?
(A || B && C && D)の場合、私の型はある種のポインタでなければならないと結論付けます。
テンプレートは次のとおりです。
template <typename T>
class is_pointer_type
{
typedef struct { char array[1]; } yes;
typedef struct { char array[2]; } no;
template <typename C> static yes test_g(decltype(&C::get));
template <typename C> static no test_g(...);
template <typename C> static yes test_e(typename C::element_type*);
template <typename C> static no test_e(...);
enum {
has_get = sizeof(test_g<T>(0)) == sizeof(yes),
has_element_type = sizeof(test_e<T>(0)) == sizeof(yes)
};
template <typename Q, bool OK = false>
struct get { struct type {}; };
template <typename Q>
struct get<Q, true>
{
typedef decltype(((Q*)nullptr)->get()) type;
};
template <typename Q, bool OK = false>
struct ptr { struct type {}; };
template <typename Q>
struct ptr<Q, true>
{
typedef typename Q::element_type* type;
};
public:
enum {
types_ok = std::is_same<
typename get<T, has_get>::type,
typename ptr<T, has_element_type>::type
>::value,
value = std::is_convertible<T, void*>::value || types_ok
};
};
これまでのところ、うまくいくようです。しかし、この推論に何か問題がありますか?不快な驚きに備える必要がありますか?const
/はどうvolatile
ですか?
更新(動機付け):
あなたが私のモチベーションを求めているコメントの中で、彼らは正しいです、私はあなたに1つ借りています。ユースケースはLua-C++バインディングライブラリです。クラスインスタンスをLuaに公開する場合、との任意の組み合わせでtemplate <typename T> push_value(T value)
基になる型を推測する必要があります。基になるクラスがすでにバインダーに登録されているかどうかを知る必要があります。U
T = U const/volatile/*/&
T = some_pointer<U>
U