声明的允许使用上下文

Permitted usage context of declarations

如下代码

#include <iostream>
#include <memory>
#include <ios>
using std::cout;
using std::endl;
using std::unique_ptr;
using std::make_unique;
using std::boolalpha;

template<typename T>
struct alloc{
    alloc();
    unique_ptr<T> operator() (void){
        return(auto up = make_unique<T>(NULL));
    }

};

int main (void){

    auto up = alloc<int>()();
    cout << boolalpha << ((up) ? 1 : 0) << endl; 
    return 0;
}

编译时出现如下错误:

g++ -ggdb -std=c++17 -Wall -Werror=pedantic -Wextra  -c code.cpp
code.cpp: In member function ‘std::unique_ptr<_Tp> alloc<T>::operator()()’:
code.cpp:14:16: error: expected primary-expression before ‘auto’
         return(auto up = make_unique<T>(NULL));
                ^~~~
code.cpp:14:16: error: expected ‘)’ before ‘auto’
make: *** [makefile:20: code.o] Error 1

早前有一个关于SO的问题报同样的错误:

以下是上述问题的已接受答案的摘录:

Declarations are not expressions. There are places where expressions are allowed, but declararions are not.

所以我根据得到的编译错误提出的问题是:

a) 标准不允许在 return 语句中使用声明吗?

b) 允许的声明上下文是什么?

注意:我故意在 return 语句中使用 auto 关键字来重现此错误。此错误最初出现在较大的代码库中。

TIA

Is the use of a declaration in a return statement not permitted by the standard?

确实不是。我们只需要检查 [stmt.jump]/1

处的语法产生式

Jump statements unconditionally transfer control.

jump-statement:
   break ;
   continue ;
   return expr-or-braced-init-listopt ;
   goto identifier ; 

没有将 "expr-or-braced-init-list" 转换为任何类型语句的产生式,因此也没有声明语句。也没有产生式将其转换为任何其他类型的声明(例如函数、名称空间或 class)。所以你不能在 return 语句的操作数中声明任何东西。

What are the permitted contexts for declarations?

几乎所有不需要显式表达式的地方。 C++ 中翻译单元的定义(一个正在翻译的文件)是每个 [basic.link]/1.

的一系列声明

A program consists of one or more translation units linked together. A translation unit consists of a sequence of declarations.

translation-unit:    
    declaration-seqopt

不同的声明有不同的结构。诸如名称空间之类的一些可能包含更多声明。其他如函数可能包含语句,这些语句本身可能是某些事物的声明语句。但最重要的是,该标准明确了语句可以出现的位置,以及只允许使用表达式的位置。