2009-06-04 9 views
7

あるクラスに特定の引数を持つコンストラクタがあるかどうかをコンパイル時にチェックする方法はありますか? ?例えばコンパイル時のクラスコンストラクタシグネチャを確認する

私はコンパイル時にSTDとそのコンストラクタ::定義され常に文字列& を確認したい
class foo { 
    foo(std::string &s) { 
    } 
}; 

。たぶんブーストはそのような機能を提供しますか?

+0

オブジェクトを作成しようとせずに意味しますか? – Naveen

+1

このコンストラクタが定義されていないときにこのコンストラクタを使用すると、コンパイラはエラーを生成します。あなたがそれを使用しないなら、なぜあなたはそれを存在させたいのですか? –

+0

提案されたチェックの面白いテストケースは、std :: string自体です。 – MSalters

答えて

3

あなたが本当にそれが必要な場合は、この機能を追加することができます。あなたのコンストラクタがなければ

static void _dummy() { std::string s; foo f(s); } 

を、コンパイルが失敗します。注意:あなたのコンストラクタはプライベートです。目的に合っていれば、_dummyはクラスの内側にあるはずです。それ以外の場合は、クラスの外に置くことができます。

また、テンプレート内で多く発生する場合は、テンプレート化したり、マクロにすることもできます。

しかし、実際に言うと、それはまだハックのように見えます。あなたはそれが本当に必要ですか?

0

あなたが求めているのは、単体テストのようです。私はcppunitのようなものをダウンロードし、それをあなたのコンパイルに統合します。

あなたが書いた単体テストは、コンパイル時にビルド/実行されます。詳細については、Unit Testingを参照してください。

+0

ユニットテストは実際にはコンパイル時ではなく、非常に明示的に尋ねられました。かなり可能であることを証明する2つのソリューションが既にあります。 – MSalters

+0

ユニットテストはコンパイル時のチェックではありませんが、コードをコンパイルするときに実行するように設定できます。これにより、おそらくあなたが探しているものが得られます。これは、コードに関する機能的な契約や前提条件を検証する方法です。 これはコンパイル時に発生する必要がある理由はありますか? –

0

あなたがチェックのこの種を必要とする場合、あなたはおそらく私が(ドキュメントがhereである)という概念ライブラリのチェックを高めるために見てみることをお勧め

チェックするいくつかの他のコンパイル時間が必要になります。あなたに役立つドキュメンテーション、クラス、マクロを見つけることができます。

3

fooが文字列から構成可能かどうかを確認する場合は、boost::is_convertibleを使用できます。例えば

BOOST_STATIC_ASSERT((boost::is_convertible<std::string, foo>::value)); 
2

ブースト1.39でコンセプトチェックの使用:取り外しまたは以下のコンパイル時エラーにfoo_c結果のコンストラクタを変更

#include <boost/concept_check.hpp> 

class foo_c 
{ 
public: 
    foo_c(std::string& s) 
    {} 
}; 

template<typename T> 
class algo_c 
{ 
BOOST_CONCEPT_ASSERT((boost::Convertible<std::string,T>)); 
public: 
    algo_c() 
    {} 
}; 

error C2440: 'initializing' : cannot convert from 'std::string' to 'foo_c'

編集: これは、homemで明示的なコンストラクタで動作するようにすることができます

template <typename T> 
struct HasTheRightConstructor 
{ 
    BOOST_CONCEPT_USAGE(HasTheRightConstructor) 
    { 
     std::string v; 
     T j(v); 
    } 
}; 
+1

このメソッドは、明示的なコンストラクタでは機能しません。デフォルト以外の引数を1つ持つコンストラクタに対してのみ機能します。変換演算子が "std :: string"からT –

+0

に設定されていればうまくいきません。明示的なctorで動作するように編集しました。正確なプロトタイプを一致させる方法を知らない(MSaltersから答えを返すことができない –

6

特定の機能が存在するかどうかを確認する一般的な方法は、そのアドレスを取得してダミー変数に割り当てることです。これはこれまで述べたテストよりもはるかに正確です。これは正確な関数の署名を検証するためです。そして、質問は具体的には約string&であり、非constなのでおそらく文字列を変更しています。

しかし、この場合、take-the-address-and-assign-it-trick:コンストラクタにはアドレスがありません。だから、どうやって署名をチェックするのですか?単純に:ダミークラスでそれに仲良くしてください。

template<typename T> 
class checkSignature_StringRef { 
    friend T::T(string&); 
}; 

これはあまりにも非常に具体的なチェックです:それもfoo::foo(std::string &s, int dummy = 0)のような同様のコンストラクタとは一致しません。

+0

VC8でコンパイルされない:classに明示的な 'T :: {ctor}'が含まれているが、インターフェイスから派生していない関数の宣言が含まれています –

+0

ここに欠陥レポートを書き留めておきます:http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#215 –

+0

gcc3でクラッシュ!gcc4でコンパイルエラー...メソッドは良く見えますが、他の誰かがコンパイルしたことを知ってうれしく思います... –

1

引数が互換性があるときにコンストラクタを基本クラスに転送し、そうでないときに何か他のことをしたいという同様の問題が出てきました。ここで

は(C++ 11のものが必要です)MSVC 2013に取り組んで一般特性である:D:

ここ
namespace detail { 
    template<class type,class...Args> 
    class constructible_from 
    { 
     template<class C> 
     static C arg(); 

     template <typename U> 
     static boost::mpl::true_ constructible_test(U *, decltype(U(arg<Args>()...)) * = 0); 
     static boost::mpl::false_ constructible_test(...); 

    public: 

     typedef decltype(constructible_test(static_cast<type*>(nullptr))) result; 

    }; 
} // namespace detail 

template<class type> 
struct constructible 
{ 
    template<class...Args> 
    struct from : 
     detail::constructible_from<type,Args...>::result {}; 
}; 

が特徴使用例ですが、私は運動としてenable_ifアプリケーションを残します

struct b{}; 
struct c{}; 
struct d : c{}; 

struct a 
{ 
    a() {} 
    a(a &) {} 
    a(b,c) {} 
    a(c) {} 
}; 


static_assert(
    constructible<a>::from<>::value, 
    "a()" 
); 
static_assert(
    constructible<a>::from<a&>::value, 
    "a(a&)" 
); 
static_assert(
    ! constructible<a>::from<const a&>::value, 
    "a(const a&)" 
); 
static_assert(
    constructible<a>::from<b,c>::value, 
    "a(b,c)" 
); 
static_assert(
    ! constructible<a>::from<b>::value, 
    "a(b)" 
); 
static_assert(
    constructible<a>::from<c>::value, 
    "a(c)" 
); 
static_assert(
    constructible<a>::from<d>::value, 
    "a(d)" 
); 
関連する問題