模板化的模板参数名称在方法头上无效
Templated template argument name is invalid on the head of the method
我有以下示例代码:
template<int Size, template<typename Tin, int S> typename Cin, template<typename Tout, int S> typename Cout>
Cout<Tout, Size> SomeTemplatedMethod(const Cin<Tin, Size> &inputData) /* Here the definition fails on Tout and Tin as unknown. */
{
Cout<Tout, Size> result; // Here Tout doesnt fail!
//Whichever we do with inputData and result
return result;
}
代码在方法的标头中失败,但在正文中没有!我发现解决这个问题的一种方法是这样做:
template<int Size, template<typename, int> typename Cin, template<typename, int> typename Cout, typename Tin, typename Tout>
Cout<Tout, Size> SomeTemplatedMethod(const Cin<Tin, Size> &inputData) /* Here the definition doesn't fail. */
{
Cout<Tout, Size> result; // Here Tout doesnt fail!
//Whichever we do with inputData and result
return result;
}
但我肯定想用第一种方式,因为它感觉更干净。。。
我正在使用vc++14。我做错了什么?,这是一个bug还是一种预期行为?
谢谢!
这是预期行为。
来自【basic.scope.el】/1:
template-template-parameter是引入名称的最小的模板参数列表。
并且,来自[basic.scope.el]/3:
模板参数名称的潜在作用域从其点开始的声明,并在其声明性区域的末尾结束。
因此,在上面的第一个示例中,例如Tin
的声明性区域是引入它的模板参数列表,其作用域的末尾是该模板参数列表的末尾。例如,您可以使用Tin
作为template< template< typename Tin, Tin arg> class Cin, ...
,但不能使用Tin
声明超出其范围的名称。
最后,请注意,对于C++14及更早版本,template<...> typename TT>
是不合法的,因为模板模板参数声明可能只使用class
关键字,而不使用typename
(您的示例在C++14中也应该失败(。除非有编译器扩展,否则在C++14中,您需要使用template<...> class TT>
。引用cppreference/template_parameters:
与类型模板参数声明不同,模板模板参数声明只能使用关键字class而不能使用typename(直到C++17(
但我肯定想使用第一种方式,因为它感觉更干净。。。
我知道这更干净,但肯定不起作用,因为Tin
、Tout
和S
的声明范围仅限于Cin
和Cout
的声明。(有关更好的解释,请参阅dfri的回答(。
因此,您必须在SomeTemplateMethod()
的模板参数列表中声明Tin
、Tout
(作为Size
(。
您的第二个版本有效,但不是最佳版本。
注意,您有五个模板参数(Tin
、Tout
、Cin
、Cout
和Size
(,并且其中只有三个(Cin
、Tin
和Size
(是可推导的(根据参数inputData
的类型(。
所以您必须至少显式其中两个:Tout
和Cout
。
如果你把Tout
和Cout
放在模板参数列表的第三和第五位,就像在你的工作代码中一样,你必须显式显示所有五个模板参数,所以你必须调用下面的函数
MyCin<int, 42> mcin;
auto mcout = SomeTemplatedMethod<42, MyCin, MyCout, int, float>(mcin);
我建议在之前放置不可推导的模板参数,在之后放置可推导的参数,例如(也使用class
而不是typename
声明模板模板参数;C++17之前需要(
template <typename Tout, template <typename, int> class Cout,
typename Tin, template <typename, int> class Cin,
int Size>
Cout<Tout, Size> SomeTemplatedMethod (Cin<Tin, Size> const & inputData)
这样你只需要显式的两个不可推导的参数
MyCin<int, 42> mcin;
auto mcout = SomeTemplatedMethod<float, MyCout>(mcin);
以下是一个完整的编译示例(但我已将int
更改为std::size_t
以获得大小(
#include <array>
template <typename Tout, template <typename, std::size_t> class Cout,
typename Tin, template <typename, std::size_t> class Cin,
std::size_t Size>
Cout<Tout, Size> SomeTemplatedMethod (Cin<Tin, Size> const &)
{
Cout<Tout, Size> result;
return result;
}
int main ()
{
std::array<int, 42u> x;
auto y = SomeTemplatedMethod<float, std::array>(x);
static_assert( std::is_same<decltype(y), std::array<float, 42u>>::value,
"!" );
}
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 具有引用返回类型的重写方法上的协变返回类型无效
- 模板化的模板参数名称在方法头上无效
- C++ 解决方法:"从类型"B*"的表达式初始化类型"C*&"的引用无效"
- 当从一个应用程序调用时,在DLL方法中创建COM接口指针是有效的,但当从另一个应用软件调用时则无效
- 方法调用中的参数无效
- 这是从二进制字符串转换为十进制值的无效方法吗?
- 不完整类型(类方法专用化)的使用无效
- 无效方法和 lambda "技巧"中的常量正确性
- 将方法从返回更改为无效
- 数组中的无效八进制数字是否有解决方法
- 方法问题 - 什么会改变值,什么不会改变?什么是无效的?
- 有效的Objective-C方法在Objective-C++中无效
- 嵌套类中的"无效协变返回类型"错误,该方法返回基于模板的对象
- 错误:在类方法声明中无效地使用void表达式
- 具有重写无效器的方法没有使任何基类方法无效
- 如何专门化模板类方法基于类型特征?使用std::enable_if对非类函数有效,但对类方法无效
- 基于jobobject调用Java方法失败(无效引用?)
- 为什么编译器不能为无效使用非静态成员函数生成解决方法
- 无效的JNI引用(从c++调用Java方法)