使用 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
相关)。
带有附加非类型模板参数(具有默认值)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
相关)。