std :: function: vérification stricte des arguments lors de la compilation
-
28-10-2019 - |
Question
Je voudrais implémenter une classe, qui contient deux rappels avec des signatures de fonction prédéfinies.
La classe a un modèle ctor, qui utilise std :: bind pour créer des membres std :: function. Je m'attendais à ce que le compilateur (g ++ 4.6) se plaigne si une fonction avec une mauvaise signature est transmise au ctor. Cependant, le compilateur accepte ce qui suit:
callback c1(i, &test::func_a, &test::func_a);
Je peux comprendre pourquoi il fait cela. J'ai essayé de créer une condition correcte pour static_assert sans succès.
Comment puis-je faire une erreur de compilation pour éviter cela?
#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;
}
MISE À JOUR : la réponse du visiteur résout mon problème initial. Malheureusement, j'ai un tas de cas connexes à résoudre, qui sont illustrés avec le code suivant ( http://ideone.com/P32sU ):
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 comme suggéré par le visiteur est déclenché ici dans ce cas, bien que la signature de la fonction soit valide:
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"
Je pense qu'il serait préférable de simplement comparer les arguments de fonction et la valeur de retour. Veuillez suggérer comment.
Merci.
La solution
Vous pouvez affirmer statiquement dans le corps du constructeur:
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");
Voir: http://ideone.com/u0z24