【问题标题】:Partial specialization difference for C++14 versus C++17?C++14 与 C++17 的部分专业化差异?
【发布时间】:2021-03-22 04:03:04
【问题描述】:

代码:

#include <iostream>
#include <cstddef>
#include <type_traits>

template <class T,T (*g)(),bool (*s)(T),class NP = std::nullptr_t,class dummy = void>  struct pfun;

template <class T,T (*g)(),bool (*s)(T)>
struct pfun<T,g,s,std::nullptr_t,typename std::enable_if<g != nullptr && (std::is_const<T>::value || s == nullptr)>::type>
  {
  pfun() {std::cout << "class pfun<T,g,s,std::nullptr_t,typename std::enable_if<g != nullptr && (std::is_const<T>::value || s == nullptr)>::type>\n";} 
  };

template <class T,T (*g)(),bool (*s)(T),class NP>
struct pfun<T,g,s,NP,typename std::enable_if<g == nullptr && s != nullptr>::type>
  {
  pfun() {std::cout << "class pfun<T,g,s,NP,typename std::enable_if<g == nullptr && s != nullptr>::type>";}
  };
 
template <class T,T (*g)(),bool (*s)(T),class NP>
struct pfun<T,g,s,NP,typename std::enable_if<g != nullptr && s != nullptr>::type>
  {
  pfun() {std::cout << "class pfun<T,g,s,NP,typename std::enable_if<g != nullptr && s != nullptr>::type>";}
  };

template <class T,T (*g)(),bool (*s)(T)>
struct pfun<T,g,s,std::nullptr_t,typename std::enable_if<g == nullptr && s != nullptr>::type> 
  {
  pfun() {std::cout << "class pfun<T,g,s,std::nullptr_t,typename std::enable_if<g == nullptr && s != nullptr>::type>";}
  };

template <class T,T (*g)(),bool (*s)(T)>
struct pfun<T,g,s,std::nullptr_t,typename std::enable_if<g != nullptr && s != nullptr>::type> 
  {
  pfun() {std::cout << "class pfun<T,g,s,std::nullptr_t,typename std::enable_if<g != nullptr && s != nullptr>::type>";}
  };
  
char const gl_r_const_ch('c');
char const gl_fun_r_read_const_ch()  { return gl_r_const_ch; }
pfun<char const,&gl_fun_r_read_const_ch,nullptr> pf_read_const_ch;

int main() { return 0; }

在 C++14 级别编译 gcc-10.2、clang-linux-11.0、VC++-14.2 和 VC++-14.2 预览时编译/链接没有问题。但是在C++17级别编译时,虽然gcc-10.2仍然编译代码没有任何问题,但是clang、VC++、VC++ preview都会报编译错误。

对于clang,结果是:

test_pmf.cpp:39:50: error: implicit instantiation of undefined template 'pfun<const char, &gl_fun_r_read_const_ch, nullptr, nullptr_t, void>'
pfun<char const,&gl_fun_r_read_const_ch,nullptr> pf_read_const_ch;
                                                 ^
test_pmf.cpp:5:95: note: template is declared here
template <class T,T (*g)(),bool (*s)(T),class NP = std::nullptr_t,class dummy = void>  struct pfun;

对于 VC++14.2 的 VC++14.2 预览结果是:

test_pmf.cpp
test_pmf.cpp(39): error C2079: 'pf_read_const_ch' uses undefined struct 'pfun<const char,gl_fun_r_read_const_ch,0x0,std::nullptr_t,void>'

代码对我来说似乎很好,但也许有人知道 C++17 的一些细微差别,这会导致 clang 和 VC++ 拒绝 C++17 中的代码,即使 gcc 认为它是正确的。有谁知道这里谁是正确的以及为什么代码不能在 C++17 中编译?

【问题讨论】:

  • 我不得不说显示的代码似乎不是最小的。您能否在保持您想要显示的行为的同时简化代码?另外,当问题是关于 14 和 17 之间的差异时,为什么你用 c++11 标记了这个问题?
  • 代码确实可以大大减少。我不愿意编辑你的问题到那种程度,所以我继续发布了一个新的question
  • 代码实际上是每个部分特化所涉及的更广泛代码的精简版本。你是对的,我可以多玩一些,看看我是否可以进一步减少它,并且仍然可以获得 gcc 和 clang/vc++ 之间的区别。但是,一旦我将更广泛的代码剥离到我的示例中,我认为该示例应该充分说明这种情况。
  • 是的,它应该被标记为 C++14 和 C++17 而不是 C++11。我可以更改那个标签吗?
  • 尽可能关注具体问题总是更可取的;例如目前尚不清楚您的问题是否源于无效的专业化,或enable_if 等。在试图找出您的代码存在什么问题时,我最终得到了我发布的版本。我认为,如果我了解该代码的内容,我将了解您的问题。另外,是的,您绝对可以编辑标签,所以请继续这样做。

标签: c++ templates c++14 c++17 partial-specialization


【解决方案1】:

我将上面的简化为:

#include <iostream>
#include <cstddef>
#include <type_traits>

template <class T,T (*g)(),bool (*s)(T),class NP = std::nullptr_t,class dummy = void>  struct pfun;

template <class T,T (*g)(),bool (*s)(T)>
struct pfun<T,g,s,std::nullptr_t,typename std::enable_if<g != nullptr && (std::is_const<T>::value || s == nullptr)>::type>
  {
  pfun() {std::cout << "class pfun<T,g,s,std::nullptr_t,typename std::enable_if<g != nullptr && (std::is_const<T>::value || s == nullptr)>::type>\n";} 
  };
  
char const gl_r_const_ch('c');
char const gl_fun_r_read_const_ch()  { return gl_r_const_ch; }
pfun<char const,&gl_fun_r_read_const_ch,nullptr> pf_read_const_ch;

// char gl_r_ch('c');
// char gl_fun_r_read_ch()  { return gl_r_ch; }
// pfun<char,&gl_fun_r_read_ch,nullptr> pf_read_ch;

int main() { return 0; }

并将其作为 bug 报告给 clang 和 vc++,并指出取消注释已注释的行并注释其他三行确实可以正常工作。

【讨论】:

    猜你喜欢
    • 2021-07-26
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多