`decltype `作为模板函数声明中模板类型规范的一部分

`decltype` as part of template type specification within declaration of a template function

本文关键字:一部分 类型 函数 decltype 声明      更新时间:2023-10-16

以下代码在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 ); 
}

注释指向有问题的行并显示修复(从设计的角度来看,这并不是真正的修复,只是一个编译修复)。几个问题:

  1. MSVC++编译这个正确吗?

  2. 如果我们要更改中的参数顺序

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?或者我在这里遗漏了一些基本的东西(也许是标准中的某个段落)?

  1. 我相信微软风投是正确的。

  2. 不能在前面的参数的声明中引用后面的参数,因为该名称还不在作用域中。为了确定fA参数的类型,fPfF都必须在作用域中,这样才能计算decltype表达式。

如果显式指定模板参数,那么它可以与gcc:一起使用

Func< true,decltype(&Foo<double>),double>( Foo< double >, -1.2, 2.1 );

将"double"直接指定为TA的参数是有效的,这意味着对TA参数使用依赖类型会阻止PFPP的类型推导。我不明白为什么会这样。