当其中一个函数未编译时,函数重载查找如何工作?

时间:2019-06-25 16:20:34

标签: c++ templates sfinae

所以我很不明白编译器如何选择函数重载。我以为我明白直到这段代码:

#include <iostream>

using namespace std;

template<class T>
struct base_type:
    public T
{
};

template<class T>
void check(T (&)[sizeof(base_type<T>)/sizeof(base_type<T>)]) {std::cout << "yeah";}

template<class T>
void check(T) {std::cout << "nah";}

union U{};
struct S{};

int main()
{
    U u[1];
    S s[1];

    check(u); // compile error
    check(s);

    return 0;
}

为什么编译器在第一次重载中无法检查数组引用的大小时,为什么没有选择check(T)的2d重载?

3 个答案:

答案 0 :(得分:3)

immediate context中的错误会导致“软”错误,该错误将从重载集中删除功能模板。编译器必须实例化base_type<T>才能评估sizeof(base_type<T>),并且该实例化所导致的任何错误在当前上下文中均不是 ,并导致硬错误。

我不确定您实际上要做什么,但是您可以使用std::enable_if_t<std::is_union_v<T>>来禁用过载。之所以起作用,是因为首先完成的std::enable_if的实例化不会引起任何错误;结果类可能根本不包含名为type的成员。对type 的访问是在即时上下文中

答案 1 :(得分:2)

SFINAE在声明而不是定义时发生,并且import numpy as np import cv2 cap = cv2.VideoCapture(0) while True: #capture frame by frame ret, img = cap.read() # gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) cv2.imshow('test', img) cv2.waitKey(0) & 0xFF cv2.destroyAllWindows() cap.release() 的声明很好,但是对其定义产生了硬错误。

Standard提供了特征base_type<U>std::is_union来进行SFINAE:

std::enable_if

对于C ++ 17,您甚至可以直接在函数内部使用template<class T, std::enable_if_t<!std::is_union<T>::value, int> = 0> void check(T (&)[1]) {std::cout << "yeah";} (即使在简化情况下,简单的if constexpr也可以):

if

答案 2 :(得分:2)

我还找到了可以引用答案的标准报价。

标准报价,C ++ 11§14.8.2/ 8:

  

只有在函数类型及其模板参数类型的直接上下文中无效的类型和表达式才能导致   演绎失败。 [注意:替代类型和   表达式可能会导致副作用,例如实例化   类模板专业化和/或功能模板   专业化,隐式定义函数的生成等。   此类副作用不在“即时范围内”,并可能导致   该程序格式不正确。 —尾注]