【问题标题】:Forcing SFINAE With a Different Return Type使用不同的返回类型强制 SFINAE
【发布时间】:2018-03-01 19:34:17
【问题描述】:

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

有没有一种方法可以让我使用这个并且与函数有不同的返回类型?

因此,overload 的参数行将触发 SFINAE:

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

但是假设我需要不同的返回类型,我怎样才能触发 SFINAE?例如,我想做这样的事情:

overload {
    [&](auto& value) -> decltype(void(value.bar()), float) { value.bar(); return 1.0F; } ,
    [](fallback_t) { cout << "fallback\n"; 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\n"; }
        } );
    }
};

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;
}

【问题讨论】:

  • 不确定您在问什么,如果您希望 lambda 具有 value.bar() 的返回类型,那么只需删除对 void 和 return value.bar() 的转换即可
  • @Praetorian 不,我只是想在 lambda 中进行一些计算并将其返回。但我只是脑放屁bipll's answer solves the problem
  • 只是猜测,但您可能正在寻找if constexpr 吗?
  • @JesperJuhl 你有兴趣,我需要根据对象是否具有功能来执行行为。如果您认为if constexpr 可以解决,请添加到链接问题!

标签: c++ templates lambda sfinae return-type


【解决方案1】:

你想要你的

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

返回float而不是void?那为什么不给 decltype 添加 float 呢?

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

【讨论】:

  • 当然可以,但无论如何我们都必须记录 value.bar() 编译的地方,这主要是 decltype 的用途。
  • 啊,如果问题提到value.bar() 的存在/合法性是选择器,那就太好了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多