【问题标题】:std::enable_if with sfinae detection of a non-member existance使用 sfinae 检测非成员存在的 std::enable_if
【发布时间】:2021-02-02 08:57:24
【问题描述】:

我正在尝试检测非成员函数(全局)的存在。在以下代码中,检测工作正常,当未使用预期签名定义 etest 函数时,两个测试都返回 0,并且在定义时返回 1。 (您可以检查注释/取消注释函数“int etest(double)”)

#include <string>
#include <iostream>

//
//uncomment the following and output will change to 1
//

//int etest(double)
//{
//    return 0;
//}

//sfinae test begin

struct Qu_Fake_Return{};

template <typename... Args>
Qu_Fake_Return etest(Args...)
{
    return {};
}


template<typename T>
struct exists_etest {
};
template<typename Ret, typename... Args>
struct exists_etest< Ret(Args...)> {
    static constexpr auto test() ->
      typename std::is_same<Ret, decltype(etest(std::declval<Args>()...))>::type { return {}; }
    static constexpr bool value = test();
};
//sfinae test end

constexpr bool constTest()
{
    auto val=exists_etest<int(double)>::value;
    return val;
}


int main()
{
    std::cout<<"exists constTest "<<constTest()<<std::endl;
    std::cout<<"exists "<<exists_etest<int(double)>::value<<std::endl;
}

我要解决的问题是使用该检测机制(或其他)以使模板可用。但是使用 enable_if 的 sfinae 检测在未定义 etest 的预期签名时拒绝编译。

以下内容无法编译并出现以下错误: 失败的要求 'exists_etest::value'; 'enable_if' 不能用于禁用此声明

//int etest(double)
//{
//    return 0;
//}

//sfinae test begin
...

template<typename N,typename std::enable_if<exists_etest<int(double)>::value,bool>::type=0>
void testTemplate(N a)
{
    std::cout<<a<<std::endl;
}

...

以下编译没有问题:

int etest(double)
{
    return 0;
}

//sfinae test begin
...

template<typename N,typename std::enable_if<exists_etest<int(double)>::value,bool>::type=0>
void testTemplate(N a)
{
    std::cout<<a<<std::endl;
}

...

关于如何基于非成员函数的存在启用模板的任何想法?

【问题讨论】:

  • std::enable_if&lt;exists_etest&lt;int(double)&gt;::value, bool&gt; 不依赖于您的模板参数,这意味着没有 SFINAE。
  • 伙计……太明显了……非常感谢,我会用你的回答来结束这个问题。

标签: c++ c++17 sfinae


【解决方案1】:
template<class A, class B>
struct second{using type=B;};
template<class A, class B>
using second_t=typename second<A,B>::type;

template<typename N,typename std::enable_if<exists_etest<int(second_t<N,double>)>::value,bool>::type=0>
void testTemplate(N a)

【讨论】:

    【解决方案2】:

    正如 cmets 中指出的那样,错误是考虑这个 SFINAE

    template<typename N,typename std::enable_if<exists_etest<int(double)>::value,bool>::type=0>
    void testTemplate(N a);
    

    不是,因为在 std::enable_if 表达式中没有使用任何模板参数。 Yakk-Adam 的回答中指出了一种解决方法,但我认为大多数时候模板将使用至少一个与测试一致的参数,在这种情况下 SFINAE 将解决。即:

    template<typename N,typename std::enable_if<exists_etest<N(double)>::value,bool>::type=0>
    void testTemplate(N a);
    
    

    【讨论】:

      猜你喜欢
      • 2011-03-23
      • 2016-06-26
      • 1970-01-01
      • 1970-01-01
      • 2012-11-27
      • 1970-01-01
      • 2013-09-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多