【问题标题】:std::enable_if predicated on std::is_convertible not deducing template correctly基于 std::is_convertible 的 std::enable_if 未正确推导模板
【发布时间】:2017-12-11 23:51:00
【问题描述】:

我有以下代码:

#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打印出TestTest() 不能转换为int,所以应该调用第二个特化)。然而,我却得到一个编译器错误:

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

prog.cpp:27:8: 错误:没有匹配函数调用‘func(int)’

prog.cpp:5:6: 注意:候选:模板 [class T, typename std::enable_if[std::is_convertible[int, T>::value, T>::type > void func(T)

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

prog.cpp:27:8: 注意:无法推断模板参数‘[anonymous>’

但是,如果我将模板化函数改为 be(同时保持其他所有内容完全相同):

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

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

【问题讨论】:

标签: c++ enable-if


【解决方案1】:
template<typename T, typename std::enable_if<std::is_convertible<int, T>::value, T>::type>

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

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

它的第二个参数声明为非类型参数,这里的typename 指定嵌套的type 是一个类型的名称。请参阅here 了解更多信息。

在第一种情况下,第二个参数是非类型的,所以函数调用 func(3) 不适合期望 func&lt;int, some_int&gt;(3) 的模板。

【讨论】:

  • @downvoter 请解释一下,我很好奇为什么这被认为值得投反对票
  • 您还没有回答问题。我在问题本身中指出,提供nullptr 的默认参数解决了这个问题 - 为什么需要默认参数?
  • @R_Kapp 我回复了前三句话。添加以下所有内容是因为我假设您不熟悉 SFINAE。
  • 无论默认参数是否正确,模板参数都会导致语法错误(如果std::enable_if 中的布尔值是false)?添加默认参数有何改变?
  • @R_Kapp 因为第二个参数是非类型的,所以你必须为它提供一个像func&lt;42&gt;(3); 这样的值,但是因为它是第二个参数,你必须写@987654332 @
猜你喜欢
  • 1970-01-01
  • 2017-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-18
  • 2012-04-05
  • 1970-01-01
相关资源
最近更新 更多