使用 class 模板的附加非类型模板参数嵌套调用可变参数方法

Nested call of variadic methods with an additional non-type template parameter of class templates

带有附加非类型模板参数(具有默认值)class 模板的可变参数方法的嵌套调用导致 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;
}

clang 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++ 中的错误引起的?


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

首先

how to do it correctly [?]

答案:加一个“template

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

there is anything wrong with the syntax used [?]

是:编译器将第一个<解释为关系运算符

// .........V  seen as relational operator ( s1->f less than i )
return s1->f< i >( ii, std::forward< Ts >( args )... );

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

题外话:从你的神马 link 我看到一个完全不同的代码有一个完全不同的问题(与 constexpr 相关)。