使用不同的返回类型强制SFINAE

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用不同的返回类型强制SFINAE相关的知识,希望对你有一定的参考价值。

所以this answer演示了如何在返回类型中使用函数来强制Substitution Failure is not an Error (SFINAE)

有没有办法可以使用它并从函数中获得不同的返回类型?

所以这个与overload相关的参数将触发SFINAE:

overload {
    [&](auto& value) -> decltype(void(value.bar())) { value.bar(); } ,
    [](fallback_t) { cout << "fallback
"; }
}

但是让我说我​​需要一个不同的返回类型,我怎么还能触发SFINAE?例如,我想做这样的事情:

overload {
    [&](auto& value) -> decltype(void(value.bar()), float) { value.bar(); return 1.0F; } ,
    [](fallback_t) { cout << "fallback
"; return 13.0F; }
}


这是最小,完整,可验证的示例。这是很多东西要读,但是如果你不想查看链接,这是我尝试添加返回类型之前涉及的代码:

struct one {
    void foo(const int);
    void bar();
};

struct two {
    void foo(const int);
};

struct three {
    void foo(const int);
    void bar();
};

template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
template<class... Ts> overload(Ts...) -> overload<Ts...>;
struct fallback_t { template<class T> fallback_t(T&&) {} };

struct owner {
    map<int, one> ones;
    map<int, two> twos;
    map<int, three> threes;

    template <typename T, typename Func>
    void callFunc(T& param, const Func& func) {
        func(param);
    }

    template <typename T>
    void findObject(int key, const T& func) {
        if(ones.count(key) != 0U) {
            callFunc(ones[key], func);
        } else if(twos.count(key) != 0U) {
            callFunc(twos[key], func);
        } else {
            callFunc(threes[key], func);
        }
    }

    void foo(const int key, const int param) { findObject(key, [&](auto& value) { value.foo(param); } ); }
    void bar(const int key) {
        findObject(key, overload {
            [&](auto& value) -> decltype(void(value.bar())) { value.bar(); } ,
            [](fallback_t) { cout << "fallback
"; }
        } );
    }
};

int main() {
    owner myOwner;

    myOwner.ones.insert(make_pair(0, one()));
    myOwner.twos.insert(make_pair(1, two()));
    myOwner.threes.insert(make_pair(2, three()));

    myOwner.foo(2, 1);
    cout << myOwner.bar(1) << endl;
    cout << myOwner.bar(2) << endl;
    cout << myOwner.foo(0, 10) << endl;
}
答案

你想要你的吗?

[&](auto& value) -> decltype(void(value.bar())) { value.bar(); } ,

返回浮动而不是空白?那么为什么不将float添加到decltype?

[&](auto& value) -> decltype(void(value.bar()), 1.0f) { value.bar(); return 1.0; }

以上是关于使用不同的返回类型强制SFINAE的主要内容,如果未能解决你的问题,请参考以下文章

以不同方式分派 r 值和 l 值并使用 sfinae 禁用一个选项

g++ 和 clang++ 使用变量模板和 SFINAE 的不同行为

如何使用 SFINAE 为枚举类中的缺失值制作 polyfill?

使用 void_t 和受保护的嵌套类的基于 SFINAE 的检测

SFINAE 用于无符号类型选择

SFINAE模板类复杂类型的静态成员定义