2017-04-24 5 views
0

クラスに指定されたシグネチャを持つコンストラクタがある場合、コンパイル時にどのように検出できますか?私は次の操作を実行したいと思います。具体的には:クラスに署名付きコンストラクタがあるかどうかを検出する

class Archive 
{ 
    // (...) 

    template <typename T> 
    T Read() 
    { 
     if constexpr(HasUnarchiveConstructor<T>()) 
     { 
      return T(*this); // constructor accepts reference to Factory 
     } 
     else 
     { 
      T t; 
      Unarchive(*this, t); // use stand alone function instead. (if this is not available either, compiling fails) 
      return t; 
     } 
    } 
} 

特定のシグネチャを持つ関数を検出するための多くの原因があります。私はしかし、コンストラクタにこれらを変換することはできません。 source 1source 2source 3以上。

template<typename T> 
using HasUnarchiveConstructorImpl = decltype(std::declval<T>() + std::declval<T>()); 

template< typename T > 
using HasUnarchiveConstructor = std::is_detected<HasUnarchiveConstructorImpl, T>; 

私は私が実行するチェックにこれを拡張することができますどのように?私は機能がプラス演算子を持っているかどうかを検出するために、以下をコンパイルしたソースからの

それとも私は別のやり方でそれをやり遂げることができますか?

答えて

1

これをどのようにチェックしたいのですか?

次のようにT{...}式にdecltype(...)を使用することもできます。

struct Foo 
{ 
    Foo(Archive&) { } 
}; 

struct Bar 
{ 
    // unsupported 
}; 

template<class T> 
using HasUnarchiveConstructorImpl = 
    decltype(T{std::declval<Archive&>()}); 

template <class T> 
using HasUnarchiveConstructor = 
    std::experimental::is_detected<HasUnarchiveConstructorImpl, T>; 

static_assert(HasUnarchiveConstructor<Foo>::value); 
static_assert(!HasUnarchiveConstructor<Bar>::value); 

live example on wandbox


またはどのように私は別の方法でそれを行うことができますか?

ハワードヒナントのanswerを参照してください。

+0

回答した内容を明確にしました。まだdownvoteの価値がある? –

+1

私は投票をしなかったが、私はそれを相殺するためにupvoteします。私はあなたの実装が非常に洞察力があると感じました。 :-) –

+1

あなたの答えは自分自身でこれを行う方法を教えてくれました。 Howardsの答えは、私がどのように多くのコードをスキップすることができるかを示しています(私はhomebrew is_detectedしか利用できません)。両方とも非常に便利でした。 –

8

は、私が使用します。

if constexpr(std::is_constructible<T, Archive&>{}) 

この特性は<type_traits>に住んでいると、既製の、あなたのために、デバッグしています。そこにあなたのために利用可能なこの問題の変種を検出するための特性の家族が全部あります。

関連する問題