(为什么)这个带有 temporary/anonymous 对象的模板 class 的实例化是一个令人烦恼的解析?

(Why) is this instantiation of a template class with a temporary/anonymous object a vexing parse?

此代码:

// main.cpp

template< typename T >
class Owner {
public:
  Owner( const T& t )
    : t_( t ) {}

  void func() { }

private:
  T t_;
};

class Foo {
};

int main( int argc, char* argv[] ) {
  Owner<Foo> owner( Foo() );

  owner.func();

  return 0;
}

生成此错误:

$ g++ --version && g++ -g ./main.cpp
g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

./main.cpp: In function ‘int main(int, char**)’:
./main.cpp:22:9: error: request for member ‘func’ in ‘owner’, which is of non-class type ‘Owner<Foo>(Foo (*)())’
   owner.func();
         ^~~~

问题:这是一个编译错误吗,因为owner的定义是一个令人烦恼的解析,如果是,为什么?
我试图梳理编译器如何将 owner 的定义解释为变量声明以外的任何东西......我可以看到它可能会如何思考“owner 是一个函数 returns Owner<Foo>" 的一个实例,但我不明白为什么括号中的 temporary/anonymous 变量不能排除它——这怎么可能与参数列表?

问题: 是否有一种变通方法允许我使用 temporary/anonymous 变量实例化 Owner<Foo> 实例? IE。使用临时 named Foo 实例实例化 Owner<Foo> 可以解决此编译器问题,但我想避免这种情况。 IE。以下工作,但我想避免创建命名 Foo 实例:

// main.cpp

template< typename T >
class Owner {
public:
  Owner( const T& t )
    : t_( t ) {}

  void func() { }

private:
  T t_;
};

class Foo {
};

int main( int argc, char* argv[] ) {
  Foo tmp;
  Owner<Foo> owner( tmp );

  owner.func();

  return 0;
}

此声明:

Owner<Foo> owner( Foo() );

确实是一个令人头疼的解析。它将 owner 声明为 returns 和 Owner<Foo> 的函数,并且只有一个参数。单个参数 Foo() 本身被解释为 returns 一个 Foo 并且没有参数的函数。

解决此问题的最简单方法是使用大括号代替圆括号:

Owner<Foo> owner{ Foo{} };

现在没有歧义,也不需要任何 Foo.

类型的命名变量