SFINAE:检测类是否有自由函数

发布于 2024-10-14 12:49:22 字数 860 浏览 1 评论 0原文

有没有办法使用 SFINAE 来检测给定类的自由函数是否重载?

基本上,我有以下解决方案:

struct has_no_f { };

struct has_f { };

void f(has_f const& x) { }

template <typename T>
enable_if<has_function<T, f>::value, int>::type call(T const&) {
    std::cout << "has f" << std::endl;
}

template <typename T>
disable_if<has_function<T, f>::value, int>::type call(T const&) {
    std::cout << "has no f" << std::endl;
}

int main() {
    call(has_no_f()); // "has no f"
    call(has_f()); // "has f"
}

简单地重载 call 不起作用,因为实际上有很多 foobar 类型,并且call 函数不知道它们(基本上 call 位于 a 内部,用户提供自己的类型)。

我无法使用 C++0x,并且我需要一个适用于所有现代编译器的工作解决方案。

注意:不幸的是,类似问题的解决方案在这里不起作用。

Is there a way, using SFINAE, to detect whether a free function is overloaded for a given class?

Basically, I’ve got the following solution:

struct has_no_f { };

struct has_f { };

void f(has_f const& x) { }

template <typename T>
enable_if<has_function<T, f>::value, int>::type call(T const&) {
    std::cout << "has f" << std::endl;
}

template <typename T>
disable_if<has_function<T, f>::value, int>::type call(T const&) {
    std::cout << "has no f" << std::endl;
}

int main() {
    call(has_no_f()); // "has no f"
    call(has_f()); // "has f"
}

Simply overloading call doesn’t work since there are actually a lot of foo and bar types and the call function has no knowledge of them (basically call is inside a and the users supply their own types).

I cannot use C++0x, and I need a working solution for all modern compilers.

Note: the solution to a similar question unfortunately doesn’t work here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不…忘初心 2024-10-21 12:49:22
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <functional>
#include <type_traits>

struct X {};
struct Y {};

__int8 f(X x) { return 0; }
__int16 f(...) { return 0; }

template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int8), int>::type call(T const& t) {
    std::cout << "In call with f available";
    f(t);
    return 0;
}

template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int16), int>::type call(T const& t) {
    std::cout << "In call without f available";
    return 0;
}

int main() {
    Y y; X x;
    call(y);
    call(x);
}

对 f() 返回类型的快速修改产生了传统的 SFINAE 解决方案。

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <functional>
#include <type_traits>

struct X {};
struct Y {};

__int8 f(X x) { return 0; }
__int16 f(...) { return 0; }

template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int8), int>::type call(T const& t) {
    std::cout << "In call with f available";
    f(t);
    return 0;
}

template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int16), int>::type call(T const& t) {
    std::cout << "In call without f available";
    return 0;
}

int main() {
    Y y; X x;
    call(y);
    call(x);
}

A quick modification of the return types of f() yields the traditional SFINAE solution.

烟柳画桥 2024-10-21 12:49:22

如果允许 boost,以下代码可能会满足您的目的:

#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
using namespace boost;

// user code
struct A {};
static void f( A const& ) {}
struct B {};


// code for has_f
static void f(...); // this function has to be a free standing one

template< class T >
struct has_f {
  template< class U >
  static char deduce( U(&)( T const& ) );

  template< class U, class V >
  static typename disable_if_c< is_same< V, T >::value, char(&)[2] >::type
  deduce( U(&)( V const& ) );

  static char (&deduce( ... ))[2];

  static bool const value = (1 == sizeof deduce( f ));
};

int main()
{
  cout<< has_f<A>::value <<endl;
  cout<< has_f<B>::value <<endl;
}

但是,有严格的限制。
该代码假定所有用户函数都具有签名 ( T const& )
所以不允许使用 ( T )
上面的函数 void f(...) 似乎需要是一个独立的函数
功能。
如果编译器按正常预期强制执行两阶段查找,可能
所有用户函数都必须出现在 has_f 类的定义之前
模板。
老实说,我对代码的实用性没有信心,但无论如何我希望
这有帮助。

If boost is allowed, the following code might meet your purpose:

#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
using namespace boost;

// user code
struct A {};
static void f( A const& ) {}
struct B {};


// code for has_f
static void f(...); // this function has to be a free standing one

template< class T >
struct has_f {
  template< class U >
  static char deduce( U(&)( T const& ) );

  template< class U, class V >
  static typename disable_if_c< is_same< V, T >::value, char(&)[2] >::type
  deduce( U(&)( V const& ) );

  static char (&deduce( ... ))[2];

  static bool const value = (1 == sizeof deduce( f ));
};

int main()
{
  cout<< has_f<A>::value <<endl;
  cout<< has_f<B>::value <<endl;
}

However, there are severe restrictions.
The code assumes that all the user functions have the signature ( T const& ),
so ( T ) isn't allowed.
The function void f(...) in the above seems to need to be a free standing
function.
If the compiler enforces two phase look-up as expected normally, probably
all the user functions have to appear before the definition of has_f class
template.
Honestly, I'm not confident of the usefulness of the code, but anyway I hope
this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文