This question already has answers here:
Where and why do I have to put the “template” and “typename” keywords?

(6个答案)


去年关闭。




如果可变参数方法的嵌套调用与类模板的其他非类型模板参数(具有默认值)一起嵌套,则将导致clang和g++的编译器错误(msvc编译没有问题)(如果被调用方法的非类型模板参数)被明确指定。可以使用以下最小示例重现这些错误:

#include <iostream>
#include <vector>

template< typename T >
struct S;

template< typename T >
struct SProxy
{
  template< int i = 20, typename... Ts >
  auto f( Ts&&... args );

  S< T >* s1;
  int     ii;
};

template< typename T >
struct S
{
  template< int i = 20, typename... Ts >
  auto f( int ii, Ts && ... args )
  {
    auto res = std::pair< int, int >( std::forward< Ts >( args )... );

    res.first  += i + ii;
    res.second += i + ii;

    return res;
  }
};

template< typename T >
template< int i, typename... Ts >
auto SProxy< T >::f( Ts&&... args )
{
  return s1->f< i >( ii, std::forward< Ts >( args )... );
}

int main( const int argc, const char* argv[] )
{
  S< int >      s;
  SProxy< int > sProxy{ &s, 3 };

  auto pair = sProxy.f< 10 >( 11, 12 );

  std::cout << pair.first << " " << pair.second << std::endl;

  return 0;
}


铛9.0.0产生的错误消息是
<source>:36:53: error: expected ')'
return s1->f< i >( ii, std::forward< Ts >( args )... );

如果将return s1->f< i >( ii, std::forward< Ts >( args )... );行更改为return s1->f( ii, std::forward< Ts >( args )... );,即使用了默认的非类型模板参数,则该代码编译(以及相应的二进制文件)对clang和g++来说就很好。

我的问题是,在最小示例中使用的构造是否不符合C++ 17标准,如果是,为什么,或者所使用的语法是否有问题,以及如何正确执行,或者(不太可能)如果错误是clang和g++中的错误的结果?

编辑:错误的编译器资源管理器链接已删除

最佳答案

首先



答:添加“template

// ........VVVVVVVVV   template added
return s1->template f< i >( ii, std::forward< Ts >( args )... );



是:编译器将第一个<解释为关系运算符
// .........V  seen as relational operator ( s1->f less than i )
return s1->f< i >( ii, std::forward< Ts >( args )... );

因此,您必须指示编译器将以下<视为模板参数列表的开始。因此,添加了“template”。

离题:从您的Godbolt链接中,我看到了一个完全不同的代码,但问题却完全不同(与constexpr相关)。

关于c++ - 可变参数方法的嵌套调用以及类模板的附加非类型模板参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59704266/

10-11 23:09
查看更多