はじめに
型Tが引数Args...から暗黙に(implicitに)構築可能かどうか判定する、is_implicitly_constructibleクラスを作りました。
動機
自作のクラスのコンストラクタが、想定通りexplicitになっている(またはなっていない)のを確認したいことがあったので作りました。
実装
クラス宣言は以下のようになります。
// 型Tが引数Args...から暗黙に構築可能かどうか調べる
template <typename T, typename... Args>
struct is_implicitly_constructible;
これを実装するには、
template <typename T>
void func(T);
があったとき、func<T>({Args...});
の形で呼び出し可能であれば、
型TはArgs...から暗黙に構築可能と言えますので、それを利用します。
// 実装のためのヘルパークラス
template <typename T, typename... Args>
struct is_implicitly_constructible_impl
{
private:
template <typename T1>
static void test_helper(T1);
template <typename T1, typename... Args1>
static auto test(int)
-> decltype(test_helper<T1>({std::declval<Args1>()...}), std::true_type());
template <typename T1, typename... Args1>
static auto test(...) -> std::false_type;
public:
using type = decltype(test<T, Args...>(0));
};
// is_implicitly_constructible定義
template <typename T, typename... Args>
struct is_implicitly_constructible
: public is_implicitly_constructible_impl<T, Args...>::type
{};
実際にはもう少し考慮しなければいけないことがあるのですが、ここではわかりやすくするため簡略化しています。
完全なソースコードはGitHubに上げてあります。
https://github.com/shibainuudon/HamonEngine/blob/develop/libs/type_traits/include/hamon/type_traits/is_implicitly_constructible.hpp
使い方
struct S1
{
S1(int);
};
struct S2
{
explicit S2(int);
};
static_assert(is_implicitly_constructible<S1, int>::value == true);
static_assert(is_implicitly_constructible<S2, int>::value == false);
用途
型Sをラッピングするような型Tを作るときに、引数からSが暗黙に構築可能であるかどうかによって、Tのコンストラクタにexplicitをつけるかどうか切り替えるときなどに使えるのではないでしょうか。
関連:https://cpprefjp.github.io/lang/cpp20/explicit_bool.html
他の選択肢
Stack Overflowの方法で暗黙に構築可能か判定することもできると思います。
https://stackoverflow.com/questions/42786565/how-to-check-if-type-is-explicitly-implicitly-constructible
しかし、この方法は任意の引数に対応していません。
is_explicitly_constructibleを定義するかどうか
is_constructible && !is_implicitly_constructible
をis_explicitly_constructible
と定義すると便利かもしれません。
しかし、implicitに構築可能である場合はexplicitにも構築可能なはずなので、名前とあっていないような気がします。1
explicitにのみ構築可能ということを表現する短い名前があるといいのですが・・・。
まとめ
is_implicitly_constructible、標準ライブラリにほしくないですか?
-
正しくするにはis_not_implicitly_constructible_but_explicitly_constructibleとか??? ↩