当前位置: 首页 > 知识库问答 >
问题:

STD::ENABLE_IF在STD::IS_COVERABLE上的谓词推导模板不正确

琴宾鸿
2023-03-14

我有以下代码:

#include <iostream>
#include <type_traits>

template <typename T, typename std::enable_if
                                 <std::is_convertible<int, T>::value, T>::type>
void func(T a)
{
    std::cout << a << std::endl;
}

template <typename T, typename std::enable_if
                                 <!std::is_convertible<int, T>::value, T>::type>
void func(T a)
{
    a.print();
}

class Test
{
public:
    void print()
    {
        std::cout << "Test" << std::endl;
    }
};    

int main()
{
    func(3);
    func("Test");
    return 0;
}

使用这段代码,我希望第一次调用func打印出3(因为int确实可以转换为int,所以应该调用第一个专门化),第二次调用func打印出test(test()不能转换为int,所以应该调用第二个专门化)。但是,我反而得到了一个编译器错误:

prog.cpp:在函数“int main()”中:

prog.cpp:5:6:注意:模板参数扣减/替换失败:

prog.cpp:27:8:注意:无法推导出模板参数“[Anonymous>”

但是,如果我将模板化函数改为:

template <typename T, typename std::enable_if
                                 <std::is_convertible<int, T>::value, T>::type* =
                                  nullptr>
void func(T a)
{
    std::cout << a << std::endl;
}

template <typename T, typename std::enable_if
                                 <!std::is_convertible<int, T>::value, T>::type* =
                                  nullptr>
void func(T a)
{
    a.print();
}

然后一切都按照我的期望编译和工作。这个额外的语法在做什么?我为什么需要它?

共有1个答案

汲雅珺
2023-03-14
template<typename T, typename std::enable_if<std::is_convertible<int, T>::value, T>::type>

如果我们要消除噪音,就会变成

template<typename T, typename Something<T>::type>

这里的typename指定嵌套的type是一个类型的名称。有关更多信息,请参见此处。

在第一种情况下,第二个参数是非类型的,因此函数调用func(3)不适合需要func (3) 的模板。

 类似资料:
  • 我正在构建一些输入检查器,需要为整数和/或双精度设置特定的函数(例如,“iPrime”应该只适用于整数)。 如果我使用作为参数,它工作得很好: 但如果我将其用作模板参数(如上所示)http://en.cppreference.com/w/cpp/types/enable_if ) 那么我有以下错误: 我不知道第二个版本出了什么问题。

  • 我发现了和类型推导的以下行为,这对我来说是意想不到的: 中的两行都会导致错误: 没有函数模板“stdfunc_test”的实例与参数列表匹配 尝试在Visual Studio 2015中编译时。 为什么类型演绎不从函数类型中演绎模板类型,有没有变通方法?

  • Stroustrup C++第4版第796页指出 “如果的条件计算为,则完全忽略它所在的整个函数声明。”和“...我们不申报任何东西。”。 我也读过这个建议的线程,在这个线程中,SFINAE只有在模板参数的参数推导中的替换使构造格式不正确时才起作用。

  • 多亏了C11,我们收到了系列的仿函数包装器。不幸的是,我一直只听到关于这些新添加的不好的消息。最受欢迎的是它们非常慢。我测试了它,与模板相比,它们真的很糟糕。 111毫秒对1241毫秒。我认为这是因为模板可以很好地内联,而通过虚拟调用覆盖内部。 显然,在我看来,模板也有其问题: 它们必须以头的形式提供,这不是您在以封闭代码形式发布库时可能不希望做的事情, 因此,我可以假设s可以用作传递函子的事实标

  • 考虑代码: Microsoft Visual Studio 2013给出以下错误: C2912:显式特化'CByteArray序列化(const HLVariant 错误C2783:“CByteArray serialize(const std::enable_if::type 错误表明没有

  • 我在旧版本的C Cookbook中看到了这段代码,这让我很困惑。这似乎是编译,但我不知道为什么代码会这样写。 T()是什么意思?这是std::accumulate的init参数——开始求和的值。我编写了一个版本,其中我将double()替换为T()(以“硬连线”模板),然后它进行编译。double()是什么意思?