SFINAE模板专业化无法正常工作

时间:2019-04-09 19:20:15

标签: c++

#include <iostream>
#include <utility>

using namespace std;

template <size_t N, typename V = int> // works if typename V = void
struct T
{
    const static int size = 0;
};

template <size_t N>
struct T<N,typename std::enable_if<(N>10)>::type>
{
   const static int size = 1;
};

int main (){
    cout << T<9>::size << endl; // 0
    cout << T<19>::size << endl;// 0  WHY?
    cout << T<10>::size << endl; //0  
}

不确定输出为什么是这样,为什么专业化没有得到体现?

2 个答案:

答案 0 :(得分:1)

现在,第二个参数始终为var request = require('request'); var cheerio = require('cheerio'); const url = 'https://stackoverflow.com/questions/tagged/web-scraping'; const host = 'https://stackoverflow.com'; function getPosts() { request(url, function(error, response, html) { if (!error && response.statusCode == 200) { var $ = cheerio.load(html); let linkstorage = []; $('.summary .question-hyperlink').each(function() { var items = $(this).text(); var links = host + $(this).attr("href"); linkstorage.push(links); }); for (const newlink of linkstorage) { request(newlink, function(error, response, html) { if (!error && response.statusCode == 200) { var $ = cheerio.load(html); var output = $(".user-details a").eq(0).text(); console.log(output); } }); } } }); } getPosts(); ,因为它是默认值:

int

但是表达式int main (){ cout << T<9, int>::size << endl; cout << T<19, int>::size << endl; cout << T<10, int>::size << endl; } 不会产生typename std::enable_if<(N>10)>::type,因此不会选择您的专业化知识。 int的默认类型为std::enable_if::type

仅当您在第二个参数中发送void时,它才起作用(当然您不希望这样做):

void

要使其按需运行,必须将默认参数设置为int main (){ cout << T<9, void>::size << endl; cout << T<19, void>::size << endl; cout << T<10, void>::size << endl; } ,或使约束始终产生void类型。

int

或者使约束成为默认参数的类型:

template <size_t N, typename V = void>
struct T
{
    const static int size = 0;
};

实际上,您可以输入任何类型,并且不会改变任何内容。只要两个类型匹配:

typename std::enable_if<(N>10), int>::type

答案 1 :(得分:0)

由于主模板中带有默认参数的template参数,当您编写T<19>::size时,您实际上写的是T<19, int>::size

现在,您的模板存在部分专业化,因此,当弄清T<19>之类的 simple-template-id 指的是哪种专业化时,编译器将尝试查找匹配的专业化项目。部分专业化。为此,它将在实际模板参数19, int和您的部分专业化中给出的模板参数之间寻找匹配项

template <size_t N>
struct T<N, typename std::enable_if<(N>10)>::type>
{     // ^-------------- this here -------------^
    …
};

第一步是找出部分专业化本身的参数的参数。在您的情况下,部分专业化具有一个参数template <size_t N>。通过比较参数化类型T<N, typename std::enable_if<(N>10)>::type>与实际类型T<19, int>得出此参数。推导得出19作为参数N的参数。替代专业化,我们得到

struct T<N, void>

作为我们专业化的推导参数列表,因为std::enable_if<true>::typevoid。参数列表19, void19, int不同,因此,专业化不是匹配项,将使用主模板。

因此,要执行此操作,必须确保std::enable_if参数产生的类型与主模板最后一个参数的默认参数匹配,即,将默认参数更改为{{ 1}}

void

或者在您希望使用专业化的情况下,让您的template <size_t N, typename = void> struct T { … }; 产生std::enable_if

int