检查SFINAE是否存在非硬件成员函数 [英] Checking whether a non-hardwired member function exists with SFINAE

查看:111
本文介绍了检查SFINAE是否存在非硬件成员函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为成员函数和运算符创建代理。它们必须具有相同的返回类型和参数,并且必须适用于作为模板参数给定的几个类。即使类没有特定的成员函数或运算符,我希望它编译,而不是失败与错误,基本上SFINAE。如果 X 有方法 f() Y 没有任何方法名为 f ,我需要代理< X> 有一个 f )以及调用 X :: f(),我需要 Proxy< Y>



我已经知道几个模板元程序设计技巧来确定一个给定的函数是否存在,如果它们启用了某个特性但是,他们都只工作在硬线函数名而不是任意的,这严重限制了它们的使用在这种情况下,因为我需要相同的结构的几个函数。



我只需要检查是否存在具有给定名称的任何函数,如果有重载变量我不需要检查是否存在特定的一个存在,自动模板扣除解决了(或所以我希望)



我当前的代码如下所示:

  template< class T& 
class Proxy
{

//使用我的resultof解决方案
template< class ... Args>
resultof(T :: f,Args ...)f(Args ... x)
{
return x.f(x ...);
}

//使用另一个返回类型提取解决方案
template< class ... Args>
typeof(T :: f(std :: declval< Args>()...))f(Args ... x)
{
return xf(x ...) ;
}

T x;

};

即使T没有任何函数f

 <$ c $ 

c> #define resultof(f,...)typeof(Param< __ VA_ARGS __> :: Func(f))

template< class ... Args>
class Param
{

public:

template< class R>
static R Func(R(*)(Args ...));

template< class R,class C>
static R Func(R(C :: *)(Args ...));

template< class R,class C>
static R Func(R(C :: *)(Args ...)const);

};


解决方案

我怀疑

 模板< typename ... Args> 
decltype(std :: declval< T&>()。f(std :: declval< Args>()...))
f(Args& ... args)
{
return xf(std :: forward< Args>(args)...);
}

应触发SFINAE并放弃 f ,其返回类型是错误的(例如不明确或不存在的重载),而不是硬错误。我不太确定,因为 T 代理的参数,而不是 f ,我根本不能解析标准的相关部分(约14.8.2我相信)。



如果没有,则可以使用

  template< typename U = T& typename ... Args> 
decltype(std :: declval< U>()。f(std :: declval< Args>()...))
f(Args& ... args)
{
return xf(std :: forward< Args>(args)...);
}

我的编译器很高兴地接受 proxy< int& p; ,与第一个选项不同。 pf(); 会导致发现找不到匹配函数错误,这与SFINAE通常一样。






我建议尽可能使用独立运算符形式:

  template< typename T ,类型名称U> 
auto operator +(Proxy< T> const& lhs,Proxy< U> const& rhs)
- > decltype(std :: declval< T const&>()+ std :: declval< U const&>())
{
return lhs.x + rhs.x;
}

是一种可能性。


I want to create proxies for member functions and operators. They must have the same return type and parameters, and must be good for several classes, which are given as template parameters. Even if the class does not have the particular member function or operator, I want it to compile instead of failing with an error, essentially SFINAE. If X has a method f() and Y does not have any method named f, I need Proxy<X> to have an f() as well that calls X::f(), and I need Proxy<Y> to compile and instantiate without any problems.

Extracting the return type from a known function is no longer a problem, after a previous question of mine. However it fails with an error if there is no such function.

I already know several template metaprogramming tricks to determine whether a given function exists, and enable a certain feature if they do, however, they all work only on hardwired function names instead of arbitrary ones, which severely limits their use in this case since I need the same construct for several functions.

I only need to check whether any function with the given name exists, if there are overloaded variants I do not need to check if a specific one exists, automatic template deduction solves that (or so I hope)

My current code looks like this:

template <class T>
class Proxy
{

    //  using my resultof solution
    template <class... Args>
    resultof(T::f, Args...) f (Args... x)
    {
        return x.f(x...);
    }

    //  using another return type extraction solution
    template <class... Args>
    typeof(T::f(std::declval<Args>()...)) f (Args... x)
    {
        return x.f(x...);
    }

    T x;

};

Which should compile even if T does not have any function named f. Unfortunately both version fail with an error.

The implementation of resultof being

#define resultof(f, ...) typeof(Param<__VA_ARGS__>::Func(f))

template <class... Args>
class Param
{

    public:

        template <class R>
        static R Func (R (*) (Args...));

        template <class R, class C>
        static R Func (R (C::*) (Args...));

        template <class R, class C>
        static R Func (R (C::*) (Args...) const);

};

解决方案

I suspect that

template<typename... Args>
decltype( std::declval<T&>().f(std::declval<Args>()...) )
f(Args&&... args)
{
    return x.f(std::forward<Args>(args)...);
}

should trigger SFINAE and discard any instantiation of f for which the return type is ill-formed (e.g. ambiguous or non-existant overload) instead of a hard error. I'm not quite sure though because T is a parameter of proxy, not f and I simply can't parse the relevant parts of the Standard (around 14.8.2 I believe). None of the examples provided in the non normative notes seems to apply.

Failing that, it's possible to use

template<typename U = T&, typename... Args>
decltype( std::declval<U>().f(std::declval<Args>()...) )
f(Args&&... args)
{
    return x.f(std::forward<Args>(args)...);
}

for which my compiler happily accepts proxy<int> p;, unlike with the first option. p.f(); results in a 'No matching function found' error, as is usual with SFINAE.


I recommend using the freestanding form of the operators where possible:

template<typename T, typename U>
auto operator+(Proxy<T> const& lhs, Proxy<U> const& rhs)
-> decltype( std::declval<T const&>() + std::declval<U const&>() )
{
    return lhs.x + rhs.x;
}

is a possibility.

这篇关于检查SFINAE是否存在非硬件成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆