自定义模板的SFINAE失败。需要了解为什么

时间:2019-06-29 23:47:48

标签: c++11 templates template-meta-programming sfinae visual-studio-2019

我的代码需要测试各种像素类型的“有效性”。例如,如果浮点像素报告(async () => { // install proxy-chain "npm i proxy-chain --save" const proxyChain = require('proxy-chain'); // change username & password const oldProxyUrl = 'http://lum-customer-USERNAMEOFLUMINATI-zone-static-country-us:PASSWORDOFLUMINATI@zproxy.lum-superproxy.io:22225'; const newProxyUrl = await proxyChain.anonymizeProxy(oldProxyUrl); const browser = await puppeteer.launch({ headless: false, args: [ '--no-sandbox', '--disable-setuid-sandbox', `--proxy-server=${newProxyUrl}` ] }); const page = await browser.newPage(); await page.goto('https://www.whatismyip.com/'); await page.screenshot({ path: 'example.png' }); await browser.close(); })(); 的{​​{1}},则无效。

因此,我有一个“验证器”模板结构,我专门针对各种像素类型(此处仅针对true)。我的代码使用全局模板函数通过SFINAE调用正确的重载

std::isnan()

这个例子很好用。选择float的{​​{1}}专业化。一切都很好。

但是后来我尝试通过专门针对// Dummy implementation breaks compilation if no overload found. template<class PEL, typename Enable=void> struct pixel_validator { }; template<class PEL> struct pixel_validator<PEL, typename std::enable_if<std::is_floating_point<PEL>::value>::type> { static bool validate(const PEL& p) { return !std::isnan(p); } }; template<class PEL> inline bool is_valid_pixel(const PEL& p) { // Dispatch to validator above return pixel_validator<PEL>::validate(p); }; void main { float x = 1.0f; std::cout << "is it valid ?" << std::boolalpha << is_valid_pixel(x); } 的自定义版本“ pixel_validator”来减少模板表达式的冗长性。

float

所以现在不用写这个:

std::enable_if

我会写

float

...因此我的验证者变为:

template<class T, class VAL=T>
struct enable_if_floating
    : std::enable_if<std::is_floating_point<T>::value, VAL>
{};

不幸的是,当我更改“ std::enable_if<std::is_floating_point<PEL>::value>::type ”以使用它时,代码无法构建。我的enable_if_floating<PEL>::value 无法正常工作,因此Visual Studio无法找到合适的专业化名称。那我的输出就不足为奇了。

template<class PEL> 
struct pixel_validator<PEL, typename enable_if_floating<PEL>::type>
{
    static bool validate(const PEL& p) { return !std::isnan(p); }
};

我的问题是,为什么?我的pixel_validator有什么问题?

注意:我甚至将此代码放在我的enable_if_floating中,只是为了进行完整性检查。如果我的模板不好,我会期望1>------ Build started: Project: TestApp7, Configuration: Debug Win32 ------ 1>TestApp7.cpp 1>C:\Test\TestApp7\TestApp7.cpp(62,34): error C2039: 'validate': is not a member of 'pixel_validator<PEL,void>' 1>C:\Test\TestApp7\TestApp7.cpp(62,34): error C2039: with 1>C:\Test\TestApp7\TestApp7.cpp(62,34): error C2039: [ 1>C:\Test\TestApp7\TestApp7.cpp(62,34): error C2039: PEL=float 1>C:\Test\TestApp7\TestApp7.cpp(62,34): error C2039: ] 1>C:\Test\TestApp7\TestApp7.cpp(62): message : see declaration of 'pixel_validator<PEL,void>' 1>C:\Test\TestApp7\TestApp7.cpp(62): message : with 1>C:\Test\TestApp7\TestApp7.cpp(62): message : [ 1>C:\Test\TestApp7\TestApp7.cpp(62): message : PEL=float 1>C:\Test\TestApp7\TestApp7.cpp(62): message : ] 1>C:\Test\TestApp7\TestApp7.cpp(82): message : see reference to function template instantiation 'bool is_valid_pixel<float>(const PEL &)' being compiled 1>C:\Test\TestApp7\TestApp7.cpp(82): message : with 1>C:\Test\TestApp7\TestApp7.cpp(82): message : [ 1>C:\Test\TestApp7\TestApp7.cpp(82): message : PEL=float 1>C:\Test\TestApp7\TestApp7.cpp(82): message : ] 1>C:\Test\TestApp7\TestApp7.cpp(62,1): error C3861: 'validate': identifier not found 1>Done building project "TestApp7.vcxproj" -- FAILED. ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== 失败,但是不会失败。

enable_if_floating

还请注意:我的现实世界代码使用的谓词比这个简单的示例节省了更多的空间

1 个答案:

答案 0 :(得分:2)

不确定是唯一的问题,但是是一个问题。

如果你写

template<class T, class VAL=T>
struct enable_if_floating
    : std::enable_if<std::is_floating_point<T>::value, VAL>
{};

默认返回的typeT,其中std::is_enable_ifvoid

所以

template<class PEL> 
struct pixel_validator<PEL, typename enable_if_floating<PEL>::type>
{
    static bool validate(const PEL& p) { return !std::isnan(p); }
};

PEL是浮点类型时,

template<class PEL> // .....VVV   should be void, not PEL
struct pixel_validator<PEL, PEL>
{
    static bool validate(const PEL& p) { return !std::isnan(p); }
};

pixel_validator声明(和主定义)不匹配的

template<class PEL, typename Enable=void>
struct pixel_validator
 { };

因为预期的第二种类型是void,而不是PEL

我看到两种可能的替代解决方案:或者您将void作为第二个模板模板参数enable_is_floating的默认值

// ...........................VVVV 
template<class T, class VAL = void>
struct enable_if_floating
    : std::enable_if<std::is_floating_point<T>::value, VAL>
 { };

或者您将PEL作为pixel_validator第二个模板参数的默认值

template <typename PEL, typename = PEL>
struct pixel_validator
 { };

我建议第一个与std::enable_if和标准C ++库同质的人。