`decltype `作为模板函数声明中模板类型规范的一部分
`decltype` as part of template type specification within declaration of a template function
以下代码在MSVC++中编译,但在GCC 4.5.1中不编译:
#include <iostream>
template< typename PT, bool pB >
struct TA
{
PT m;
TA( PT fT ) :
m( fT )
{
std::cout << "TA<" << pB << ">::TA() : " << m << std::endl;
}
PT operator()( PT fT )
{
std::cout << "TA<" << pB << ">::() : " << m << " and " << fT << std::endl;
return ( m );
}
};
template< typename PT >
PT Foo( PT fT )
{
std::cout << "Foo() : " << fT << std::endl;
return ( fT );
}
// Does not compile in GCC 4.5.1, compiles in MSVC++2010.
// Substitute TA< decltype( fF( std::forward<PP>( fP ) ) ), pB > with
// TA< double, pB > to compile with GCC.
template< bool pB, typename PF, typename PP >
auto Func( PF fF, PP && fP, TA< decltype( fF( std::forward<PP>( fP ) ) ), pB > && fA )
-> decltype( fF( std::forward<PP>( fP ) ) )
{
decltype( fF( std::forward<PP>( fP ) ) ) lResult( fF( std::forward< PP >( fP ) ) );
fA( lResult );
return ( lResult );
}
int main( void )
{
Func< true >( Foo< double >, -1.2, 2.1 );
return ( 0 );
}
注释指向有问题的行并显示修复(从设计的角度来看,这并不是真正的修复,只是一个编译修复)。几个问题:
MSVC++编译这个正确吗?
如果我们要更改中的参数顺序
auto Func( PF fF, PP && fP, TA< decltype( fF( std::forward<PP>( fP ) ) ), pB > && fA )
至
auto Func( PF fF, TA< decltype( fF( std::forward<PP>( fP ) ) ), pB > && fA, PP && fP )
它不会编译,因为编译器将TA< decltype( fF( std::forward<PP>( fP ) ) ), pB >
中的fP
视为未声明的变量。从逻辑上讲,编译器在这一点上真的需要知道fP
吗?因为它是带有尾部返回类型的函数,所以它无论如何都不解析整个声明吗?为什么它不能"跳过"第二个函数参数,看看稍后函数声明中是否声明了fP
?或者我在这里遗漏了一些基本的东西(也许是标准中的某个段落)?
-
我相信微软风投是正确的。
-
不能在前面的参数的声明中引用后面的参数,因为该名称还不在作用域中。为了确定
fA
参数的类型,fP
和fF
都必须在作用域中,这样才能计算decltype
表达式。
如果显式指定模板参数,那么它可以与gcc:一起使用
Func< true,decltype(&Foo<double>),double>( Foo< double >, -1.2, 2.1 );
将"double"直接指定为TA
的参数是有效的,这意味着对TA
参数使用依赖类型会阻止PF
和PP
的类型推导。我不明白为什么会这样。
相关文章:
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 将类型声明为类型模板参数的模板参数的一部分是否合法?
- 检查模板类型 T 是否为 C++17 中的可变参数包的一部分
- C++11 标准中的哪一部分规定了基元数据类型大小之间的相对顺序?
- 如何进行编译时type_check并且仅在类成员的类型与类型匹配时才编译类的一部分?
- 关联容器,比较函数不是元素类型的一部分吗?
- 联合而不是aligned_storage_t作为容器节点类型的一部分
- 如何将字节阵列的一部分施放为特定类型
- 模板参数是否可以无缝匹配类型和模板,也许是可变变量的一部分
- 类型别名是否用作函数类型参数的一部分,是函数签名的一部分
- 函数的返回类型是损坏名称的一部分吗?
- 为什么参数修饰符(即'const'或"易失性")不被视为函数类型或签名的一部分?
- 为什么"noexcept"说明符不是函数类型的一部分?
- 作为C++库 API 一部分的第三方类型以及潜在的 ABI 不一致
- "外部"C""是函数类型的一部分吗?
- 清楚地说明 * 和 & 作为类型的一部分和作为取消引用/address_of操作符之间的区别
- `decltype `作为模板函数声明中模板类型规范的一部分
- std::unique_ptr将deleter作为类型的一部分有什么好处
- std::function 的模板参数(签名)不是其类型的一部分吗?