加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 是否有通用的方法来消除SFINAE的decltype条件?

发布时间:2020-12-16 10:11:30 所属栏目:百科 来源:网络整理
导读:我有十几个函数,它们有两个参数:泛型和特定类型.例如.: template class A,class Bvoid foo(A a,B b){ cout "generic fallback" endl;}template class Avoid foo(A a,int i){ cout "generic int" endl;}template class Avoid foo(A a,string s){ cout "gene
我有十几个函数,它们有两个参数:泛型和特定类型.例如.:

template <class A,class B>
void foo(A& a,B& b)
{
    cout << "generic fallback" << endl;
}

template <class A>
void foo(A& a,int &i)
{
    cout << "generic int" << endl;
}

template <class A>
void foo(A& a,string& s)
{
    cout << "generic str" << endl;
}

我想创建一个重载,只要A是特定结构的实例[1]就会调用它.到目前为止我想出的最好的是:

struct mine
{
    int is_special;
};

template <class A,class B>
auto foo(A& a,B& b) -> decltype(A::is_special,void())
{
    cout << "specialized fallback" << endl;
}

我想要的结果是:

int x;
string y;
float z;
string generic;
mine special;

foo(generic,x); // generic int
foo(generic,y); // generic string
foo(generic,z); // generic fallback
foo(special,x); // specialized fallback
foo(special,y); // specialized fallback
foo(special,z); // specialized fallback

但是,上面的代码不起作用,因为对于特殊情况,存在模糊的重载.如果A :: is_special不是有效类型,是否有任何简单的方法可以使这些函数只被创建?理想情况下,我会用以下内容注释每个函数:

template <class A,B& b) -> decltype(doesnt_work(A::is_special),void())
// ...

在更一般的情况下,我也要问:鉴于任何“正面”SFINAE测试会导致测试结果导致函数或类被创建,是否有任何方法可以否定该测试专门用于其他情况?实质上,相当于if … else与SFINAE相同.

我确实得到了这个案例,但是我必须将所有foo重命名为foo_imp,将一个long参数添加到泛型参数,将一个int参数添加到专用的参数,然后定义一个调用它们的foo(ideone代码here).这似乎不太理想,因为它不是那么简单,尽管无论如何我必须修改所有现有的foos.

[1]请注意,我不能使用类型的名称,因为它是一个嵌套模板,因此会导致不可导入的上下文.

解决方法

In essence,the equivalent of if ... else if with SFINAE.

您可以使用额外参数手动控制重载决策:

template<int I> struct rank : rank<I-1> { static_assert(I > 0,""); };
template<> struct rank<0> {};

template <class A,B& b,rank<10>) -> /*some SFINAE */
{
}

template <class A,rank<9>) -> /* some other SFINAE */
{
}

// ...

template <class A,rank<0>)
{
// fallback
}

template <class A,B& b) { return foo(a,b,rank<20>()); }

具有最高“等级”的可行过载将通过过载分辨率来选择.

您不能直接否定临时SFINAE约束(“签名中使用的此表达式必须格式良好”).您需要编写一个实际特征来检测它,然后否定结果.最简单的方法是使用std::experimental::is_detected_v,最近投入了库基础知识TS的v2:

template<class T>
using is_special_t = decltype(T::is_special);

template <class A,B& b) -> std::enable_if_t<!std::experimental::is_detected_v<is_special_t,A>>
{
    cout << "generic fallback" << endl;
}

template <class A,class B>   
auto foo(A& a,B& b) -> std::enable_if_t<std::experimental::is_detected_v<is_special_t,A>>
{
    cout << "specialized fallback" << endl;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读