本文介绍了如何调用成员函数只有当对象恰好有它吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 I have a function f that receives a value val of type T (templated). Is there any way to call a member function on val only if the type has such a member function?Example:struct Bar { void foo() const {}};template<class T>void f(T const& val) { // Is there any way to call *only* if foo() is available on type T? // SFINAE technique? val.foo();}int main() { Bar bar; f(bar); f(3.14);}Sounds like the SFINAE technique to me, maybe using boost::enable_if, but I don't know how to make it work here. Note that I can't easily change the Bar type in the example. I know it would be easy if Bar contained some certain typedef, etc., which signals that the function is available.Needless to say, I don't know the set of types T that f will be called with. Some have the foo member function, some don't. 解决方案 You can do this as illustrated by the test program below (built withGCC 4.7.0 or clang 3.1). The static template function has_void_foo_no_args_const<T>::eval(T const & t) will invoke t.foo() if the method void T::foo() const exists and is public. It willdo nothing if there is no such method. (And of course a compile error willresult if the method is private.)This solution is adapted and extended from the method-introspectingtemplate I contributed here. Youcan read that answer for an explanation of how the SNIFAE logic works,and also to see how the technique might be generalised to parameterizethe properties of the function-signature you are probing.#include <iostream>/*! The template `has_void_foo_no_args_const<T>` exports a boolean constant `value` that is true iff `T` provides `void foo() const` It also provides `static void eval(T const & t)`, which invokes void `T::foo() const` upon `t` if such a public member function exists and is a no-op if there is no such member.*/ template< typename T>struct has_void_foo_no_args_const{ /* SFINAE foo-has-correct-sig :) */ template<typename A> static std::true_type test(void (A::*)() const) { return std::true_type(); } /* SFINAE foo-exists :) */ template <typename A> static decltype(test(&A::foo)) test(decltype(&A::foo),void *) { /* foo exists. What about sig? */ typedef decltype(test(&A::foo)) return_type; return return_type(); } /* SFINAE game over :( */ template<typename A> static std::false_type test(...) { return std::false_type(); } /* This will be either `std::true_type` or `std::false_type` */ typedef decltype(test<T>(0,0)) type; static const bool value = type::value; /* Which is it? */ /* `eval(T const &,std::true_type)` delegates to `T::foo()` when `type` == `std::true_type` */ static void eval(T const & t, std::true_type) { t.foo(); } /* `eval(...)` is a no-op for otherwise unmatched arguments */ static void eval(...){ // This output for demo purposes. Delete std::cout << "T::foo() not called" << std::endl; } /* `eval(T const & t)` delegates to :- - `eval(t,type()` when `type` == `std::true_type` - `eval(...)` otherwise */ static void eval(T const & t) { eval(t,type()); }};// For testingstruct AA { void foo() const { std::cout << "AA::foo() called" << std::endl; }};// For testingstruct BB { void foo() { std::cout << "BB::foo() called" << std::endl; }};// For testingstruct CC { int foo() const { std::cout << "CC::foo() called" << std::endl; return 0; }};// This is the desired implementation of `void f(T const& val)` template<class T>void f(T const& val) { has_void_foo_no_args_const<T>::eval(val);}int main() { AA aa; std::cout << (has_void_foo_no_args_const<AA>::value ? "AA has void foo() const" : "AA does not have void foo() const") << std::endl; f(aa); BB bb; std::cout << (has_void_foo_no_args_const<BB>::value ? "BB has void foo() const" : "BB does not have void foo() const") << std::endl; f(bb); CC cc; std::cout << (has_void_foo_no_args_const<CC>::value ? "CC has void foo() const" : "CC does not have void foo() const") << std::endl; f(cc); std::cout << (has_void_foo_no_args_const<double>::value ? "Double has void foo() const" : "Double does not have void foo() const") << std::endl; f(3.14); return 0;}This program outputs:AA has void foo() constAA::foo() calledBB does not have void foo() constT::foo() not calledCC does not have void foo() constT::foo() not calledDouble does not have void foo() constT::foo() not called 这篇关于如何调用成员函数只有当对象恰好有它吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
11-01 05:46