2016-12-16 4 views
0

を変更する関数ポインタを経由して可変引数関数に渡ささまざまなタイプの.cppファイルで、私はそのマップを初期化しています:、paramsが、私はいくつかの静的関数を持つクラスと、これらの関数へのポインタを含むマップを持って自分の価値

template <typename ... argsType> 
    static bool Call(std::string const& Key, argsType&& ... Args) 
    { 
     using prototype = bool(*)(argsType ...); 
     return reinterpret_cast<prototype>(m_FunctionMap.at(Key))(Args ...); 
     //return reinterpret_cast<prototype>(m_FunctionMap.at(Key))(std::forward<argsType>(Args) ...); // this has the same issue 
    } 

今、私はこのコードを実行すると:

std::unordered_map<std::string, Conditions::cbType> const Conditions::m_FunctionMap 
{ 
    { "Equal_int", MakeMapVal(&Equal_int) }, 
    { "Equal_float", MakeMapVal(&Equal_float) }, 
    { "Greater_int", MakeMapVal(&Greater_int) }, 
    { "Greater_float", MakeMapVal(&Greater_int) }, 
    { "Between_int", MakeMapVal(&Between_int) }, 
    { "Between_float", MakeMapVal(&Between_float) }, 
}; 

その後、私は自分の名前でこれらの静的関数を呼び出すために、クラスConditionsにメソッドを追加しましたそれぞれの静的機能を正しく呼び出すCall(std::string const& Key, argsType&& ... Args)メソッドを呼び出します。例えば:

Call("Greater_int", 42, 40); 

しかし、Greater_int()関数内でそれらの2つのパラメータは、42と40、それ以上ではなく、いくつかのランダムな値。しかし、Call関数では、これらの値は正しく4240です。したがって、reinterpret_castを介して関数ポインタを呼び出すと、これらの値が変化します。

私がここで間違っていることは何ですか?

+3

私がで掘っが、何不足している可能性が高いのは、 'のstd :: decay'の使用であるしていません。全体として、これは良いプログラミングの習慣ではありません。非常に型が危険で、エラーが発生しやすい適切に設計されたクラス階層では、すべての型が正しい場合を除いて、コンパイルすべきではありません。あなたは解決しようとしている問題が何であれ、あなたのアプローチを完全に再考し、タイプセーフな完全な解決策を見つけようとするべきです。 –

+1

[@SamVarshavchikのコメントに続く]そして、この目的のために、実際に解決しようとしている問題を述べるために質問を編集することをお勧めします。 – Rerito

答えて

2

あなたは未定義の動作の荒野にいます。 reinterpret_castは無関係な型からキャストしていますが、これは悪いことです。キャストを削除し、コンパイラを他の方法で幸せにしてください。

+0

私はこれらの静的関数を持っています。これらはすべて 'bool'を返します。名前/キーでこれらを呼び出す必要がありますが、実行時にテキストファイル(小さなスクリプトなど)から読み込みます。彼らは異なるタイプのパラメタの数が異なっています。私はそれ以外の方法で関数ポインタを介して解決できない場合はどうすればよいですか? – Matthias

+0

これらの関数がすべて同じシグネチャ(たとえば、ある種類のバリアントオブジェクトを受け入れる)を持っていることを確認する必要があります。この型へのポインタを使用し、バリアントにデータを呼び出して関数を呼び出します。基本的には、あなたのコードにreinterpret_castは全くないはずです。 – SergeyA

0

私が誤解していない限り、異なるタイプの解析と比較を可能にするDSLを作成する必要があります。

これは、boost::variantで非常に簡単に実行できます。これは単なる定型文であり、異種の型の比較演算を定義する問題です。

小さいながらも完全な例:

#include <boost/variant.hpp> 
#include <boost/operators.hpp> 
#include <string> 
#include <iostream> 
#include <iomanip> 

// define the concept of equality in my scripting language 
struct is_equal : boost::static_visitor<bool> 
{ 
    // x == x is easy 
    template<class T> 
    bool operator()(const T& l, const T& r) const { 
     return l == r; 
    } 

    // define the concept of comparing strings to integers 
    bool operator()(const std::string& l, const int& r) const { 
     return l == std::to_string(r); 
    } 

    // and integers to strings 
    bool operator()(const int& l, const std::string& r) const { 
     return (*this)(r, l); 
    } 
}; 

struct is_less : boost::static_visitor<bool> 
{ 
    // x == x is easy 
    template<class T> 
    bool operator()(const T& l, const T& r) const { 
     return l < r; 
    } 

    // define the concept of comparing strings to integers 
    bool operator()(const std::string& l, const int& r) const { 
     return l < std::to_string(r); 
    } 

    // and integers to strings 
    bool operator()(const int& l, const std::string& r) const { 
     return (*this)(r, l); 
    } 
}; 

struct emit : boost::static_visitor<std::ostream&> 
{ 
    emit(std::ostream& os) : os_(os) {} 

    // x == x is easy 
    template<class T> 
    std::ostream& operator()(const T& l) const { 
     return os_ << l; 
    } 

    std::ostream& operator()(const std::string& s) const { 
     return os_ << std::quoted(s); 
    } 

    std::ostream& os_; 
}; 

struct scriptable_value 
: boost::less_than_comparable<scriptable_value> 
, boost::equality_comparable<scriptable_value> 
{ 
    using variant_type = boost::variant<std::string, int>; 

    scriptable_value(std::string v) : variant_(std::move(v)) {} 
    scriptable_value(int v) : variant_(v) {} 

    variant_type const& as_variant() const { 
     return variant_; 
    } 

private: 
    variant_type variant_; 
}; 

bool operator==(scriptable_value const& l, scriptable_value const& r) 
{ 
    return boost::apply_visitor(is_equal(), l.as_variant(), r.as_variant()); 
} 

bool operator<(scriptable_value const& l, scriptable_value const& r) 
{ 
    return boost::apply_visitor(is_less(), l.as_variant(), r.as_variant()); 
} 

std::ostream& operator<<(std::ostream& os, scriptable_value const& r) 
{ 
    return boost::apply_visitor(emit(os), r.as_variant()); 
} 


int main() 
{ 
    auto x = scriptable_value(10); 
    auto y = scriptable_value("10"); 
    auto x2 = scriptable_value(9); 
    auto y2 = scriptable_value("9"); 

    std::cout << x << " == " << y << " : " << std::boolalpha << (x == y) << std::endl; 
    std::cout << x << " != " << y << " : " << std::boolalpha << (x != y) << std::endl; 
    std::cout << x << " == " << y2 << " : " << std::boolalpha << (x == y2) << std::endl; 
    std::cout << x << " != " << y2 << " : " << std::boolalpha << (x != y2) << std::endl; 

    std::cout << x << " < " << y << " : " << std::boolalpha << (x < y) << std::endl; 
    std::cout << x << " >= " << y << " : " << std::boolalpha << (x >= y) << std::endl; 
    std::cout << x << " < " << y2 << " : " << std::boolalpha << (x < y2) << std::endl; 
    std::cout << x << " >= " << y2 << " : " << std::boolalpha << (x >= y2) << std::endl; 

    std::cout << x << " == " << x2 << " : " << std::boolalpha << (x == x2) << std::endl; 
    std::cout << x << " != " << x2 << " : " << std::boolalpha << (x != x2) << std::endl; 

} 

予想される出力:

10 == "10" : true 
10 != "10" : false 
10 == "9" : false 
10 != "9" : true 
10 < "10" : false 
10 >= "10" : true 
10 < "9" : false 
10 >= "9" : true 
10 == 9 : false 
10 != 9 : true 
関連する問題