2011-12-06 11 views
4

あらかじめ定義された関数シグネチャで2つのコールバックを保持するクラスを実装したいと思います。std :: function:コンパイル時の引数の厳密な検証

クラスにはstd :: bindを使用してstd :: functionメンバーを作成するテンプレートctorがあります。私は、コンパイラ(g ++ 4.6)が間違った署名を持つ関数がctorに渡されると文句を言ってくれると予想しました。しかし、コンパイラは、次のことを受け入れ:

callback c1(i, &test::func_a, &test::func_a); 

それはそれを行う理由を私は理解することができます。 static_assertのための適切な条件を構築しようとしましたが、成功しませんでした。

これを防ぐにはどうすればコンパイル時エラーが発生しますか?

#include <functional> 

using namespace std::placeholders; 

class callback { 
public: 
    typedef std::function<bool(const int&)>  type_a; 
    typedef std::function<bool(int&)>  type_b; 

    template <class O, typename CA, typename CB> 
     callback(O inst, CA ca, CB cb) 
     : 
     m_ca(std::bind(ca, inst, _1)), 
     m_cb(std::bind(cb, inst, _1)) 
     { } 

private: 
    type_a m_ca; 
    type_b m_cb; 
}; 


class test { 
public: 
    bool func_a(const int& arg) { return true; } 
    bool func_b(int& arg) { arg = 10; return true; } 
}; 

int main() 
{ 
    test i; 
    callback c(i, &test::func_a, &test::func_b); 

// Both should fail at compile time 

    callback c1(i, &test::func_a, &test::func_a); 
// callback c2(i, &test::func_b, &test::func_b); 

    return 0; 
} 

UPDATE:訪問者からの回答は、私の最初の問題を解決します。関数の署名が有効であるが、この場合のためにここにトリガされ、訪問者によって示唆されるように

class test { 
public: 
    virtual bool func_a(const int& arg) { return true; } 
    virtual bool func_b(int& arg) { arg = 10; return true; } 
}; 

class test_d : public test { 
public: 
    virtual bool func_b(int& arg) { arg = 20; return true; } 
}; 

int main() 
{ 
    test_d i; 
    callback c(i, &test_d::func_a, &test_d::func_b); 
    return 0; 
} 

static_assert:生憎私は、次のコード(http://ideone.com/P32sU)で実証されている解決に関連する事例の束を有する

prog.cpp: In constructor 'callback::callback(O, CA, CB) [with O = test_d, CA = bool (test::*)(const int&), CB = bool (test_d::*)(int&)]': 
prog.cpp:41:51: instantiated from here 
prog.cpp:17:12: error: static assertion failed: "First function type incorrect" 

私は、関数の引数と戻り値を比較するだけでよいと思います。どうか提案してください。

ありがとうございます。

答えて

1

あなたは、静的コンストラクタ本体に主張することができます

static_assert(std::is_same<CA, bool(O::*)(const int&)>::value, "First function type incorrect"); 
static_assert(std::is_same<CB, bool(O::*)(int&)>::value, "Second function type incorrect"); 

参照:http://ideone.com/u0z24

+0

グレート!私はstd :: is_sameを使用しようとしていましたが、関数シグニチャーの代わりに誤ってtype_a/type_bを取りました。ところで、関数の型をstd :: function typedef(DRY)から推論することは可能ですか? – matejk

+0

std :: functionはテンプレート引数として与えられたパラメータ型で呼び出すことができる限り、どんな種類の関数をも受け入れるので、ここではあまり使用しません。 - メタ関数を使って可能な、技術的に 'type_a'から' bool(int&) 'を抽出する方法については、http://ideone.com/dU3b7 – visitor

関連する問題