a non-type template parameter cannot have type [closed]

做~自己de王妃 提交于 2021-01-28 11:50:54

问题


For anyone stumbling upon this question in the future, the original question was: "How to get the simplest example (Point) from this article to compile with GCC or CLANG?"

  • Edit 1 shows the smallest possible code that fails with CLANG but compiles with GCC (both with -std=c++2a).
  • Edit 2 shows further code added, that breaks GCC as well.

The author of the article (@BarryRevzin) was kind enough to comment the reason why this won't work yet, thank you Barry!

Edit 1:

Simplified code below works with gcc 9.3.0 but not with clang 10.0.0:

struct Point {                                                                                                                                                                               
   int x = 0;                                                                                                                                                                                
   int y = 0;                                                                                                                                                                                
};                                                                                                                                                                                           

template <Point> // ok in C++20                                                                                                                                                              
void takes_tmpl_point();                                                                                                                                                                     

int main()                                                                                                                                                                                   
{
    // EMPTY
}

Edit 2:

The original code, as per the author, won't work on GCC or CLANG as of yet due to the compilers being behind the standard a bit. Original code below:

struct Point {                                                                                                                                                                               
   int x = 0;                                                                                                                                                                                
   int y = 0;                                                                                                                                                                                
};                                                                                                                                                                                           

template <Point> // ok in C++20                                                                                                                                                              
void takes_tmpl_point();                                                                                                                                                                     

int main()                                                                                                                                                                                   
{                                                                                                                                                                                            
   takes_tmpl_point<{.x=1, .y=2}>(); // x=1, y=2
}

This will result in the following compilation error on GCC 9.3:

test.cpp: In function ‘int main()’:
test.cpp:11:35: error: no matching function for call to ‘takes_tmpl_point<{1, 2}>()’
   11 |    takes_tmpl_point<{.x=1, .y=2}>(); // x=1, y=2
      |                                   ^
test.cpp:7:6: note: candidate: ‘template<Point <anonymous> > void takes_tmpl_point()’
    7 | void takes_tmpl_point();
      |      ^~~~~~~~~~~~~~~~
test.cpp:7:6: note:   template argument deduction/substitution failed:
test.cpp:11:35: error: could not convert ‘{1, 2}’ from ‘<brace-enclosed initializer list>’ to ‘Point’
   11 |    takes_tmpl_point<{.x=1, .y=2}>(); // x=1, y=2
      |                                   ^

And the following error on clang 10.0.0:

test.cpp:6:16: error: a non-type template parameter cannot have type 'Point'
template <Point> // ok in C++20
               ^
test.cpp:11:21: error: expected expression
   takes_tmpl_point<{.x=1, .y=2}>(); // x=1, y=2
                    ^
2 errors generated.

Compilers used:

  • clang: clang version 10.0.0-4ubuntu1
  • gcc: gcc (Ubuntu 9.3.0-10ubuntu2) 9.3.0

回答1:


Clang just doesn't implement class types as non-type template parameters yet, see P1907 in this table.

gcc does implement them but there's actually an issue here. The grammar for template-argument doesn't actually allow for a braced-init-list. This is a clear language defect (there was never a reason to have such a thing before P1907 but now there's certainly no reason to not have it). This is a language bug at the moment. Nevertheless, gcc went ahead and does support a braced-init-list as a template argument... just not a designated-initializer-list.

So that blog post of mine is running ahead of the actual language by a bit... Until the language catches up, even though this is technically unsupported:

takes_tmpl_point<{.x=1, .y=2}>(); 

This is definitely valid:

takes_tmpl_point<Point{.x=1, .y=2}>();


来源:https://stackoverflow.com/questions/61940342/a-non-type-template-parameter-cannot-have-type

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!