考虑以下:
template<typename Der>
struct Base {
// NOTE: if I replace the decltype(...) below with auto, code compiles
decltype(&Der::operator()) getCallOperator() const {
return &Der::operator();
}
};
struct Foo : Base<Foo> {
double operator()(int, int) const {
return 0.0;
}
};
int main() {
Foo f;
auto callOp = f.getCallOperator();
}
Run Code Online (Sandbox Code Playgroud)
我想在CRTP基类中创建一个成员函数,其返回类型取决于operator()
派生类中的签名.但decltype(&Der::operator())
无法编译; 将operator()
在成员函数Foo
是不可见的.我假设这是因为基类模板在Foo
完全定义之前被实例化.
令人惊讶的是,如果我auto
为返回类型放置它编译.我假设这auto
会使编译器从函数体中推导出返回类型并失败 - 因为正文使用了未完全定义的Foo
类型.
MSVC 2015.3和Clang 3.8的行为相同
为什么代码开始使用auto
?难道auto
类型推演莫名其妙"延迟"的实例?或者使用与手写返回类型表达式不同的上下文?
在下面的示例中,A
有一个成员typedef Instantiate
导致实例化B<A>
.
template<typename T>
struct B
{
typedef typename T::Before Before; // ok
typedef typename T::After After; // error: no type named 'After' in 'A<int>'
};
template<typename T>
struct A
{
typedef int Before;
typedef typename B<A>::After Instantiate;
typedef int After;
};
template struct A<int>; // instantiate A<int>
Run Code Online (Sandbox Code Playgroud)
我尝试过的所有编译器都报告说,虽然A::Before
可见但A::After
并非如此.这种行为是否符合标准?如果是这样,标准在哪里指定A
在实例化期间哪些名称应该可见B<A>
?
如果依赖名称"在模板实例化时查找",那么在由模板参数限定的名称场景中,这意味着什么T::After
?
编辑:请注意,当A不是模板时,会发生相同的行为:
template<typename T>
struct B
{
typedef typename T::Before Before; // ok
typedef typename T::After …
Run Code Online (Sandbox Code Playgroud) 是否允许c ++ 14中的成员函数返回类型推导,或仅适用于自由函数?
我问,因为我有点暗示它会起作用,但是在gcc 4.8.1中我得到一个内部编译器错误("在gen_type_die_with_usage中").我第一次遇到这样一个神秘的错误,所以我有点怀疑; 我知道他们从那时起就改变了规范.
为清楚起见,这对我有用:
auto foo() {return 5;}
Run Code Online (Sandbox Code Playgroud)
但这不是:
class Bar{
auto baz() {return 5;}
}
Run Code Online (Sandbox Code Playgroud)
标准草案允许这样做吗?