首先,一些标准引用的段落
如果在依赖于某些周围模板Y的模板参数的上下文中引用模板特化X,则给定的实例化点取决于Y的实例化点。
如果X是函数模板特化,则实例化点就是Y。
如果X是类模板专业化,则实例化点紧接Y的实例化点。否则,给定的实例化点将绑定到命名空间范围声明/定义(D)的位置,该范围包含引用X的语句。
如果X是函数模板特化,则实例化点紧随D之后。
如果X是类模板专业化,则实例化点紧接D之前。
此处有一些代码
#include <iostream>
template<int N>
struct state {
friend auto call(state<N>);
};
template<int N>
struct add_state {
friend auto call(state<N>) {
return N;
}
};
template<typename T, int N>
T show() {
add_state<N> d;
return T{};
}
template<typename T,int N>
class data {
public:
T c = show<T,N>();
};
#1,#3,#2
int main() {
data<int, 0> t;
call(state<0>{});
}
因此,根据上述规则,在实例化类data<int, 0>
时,实例化点位于#1。
然后show<T,N>
取决于模板类数据的模板参数。因此,show<int,0>
的实例化点在#2。
然后add_state<N>
取决于模板功能展示的模板参数。因此,根据规则,add_state<0>
的实例化点在#3。
已在#3 auto call(state<0>)
处定义了call(state<0>{})
,但实际上,编译器报告的错误如下:
c语:
main.cpp:24:2: error: function 'call' with deduced return type cannot be used before it is defined
call(state<0>{});
^
main.cpp:4:14: note: 'call' declared here
friend auto call(state<N>);
^
1 error generated.
g ++:
main.cpp: In function ‘int main()’:
main.cpp:24:17: error: use of ‘auto call(state<0>)’ before deduction of ‘auto’
call(state<0>{});
^
为什么?我是否了解实例化点有一些错误? 如果没有,为什么编译器会报告这些错误?
答案 0 :(得分:2)
根据[temp.inst]/2.1,当隐式实例化类模板时,仅实例化好友声明:
类模板专门化的隐式实例化导致声明的隐式实例化,而不是类成员的定义,默认参数或noexcept-specifiers的隐式实例化。函数,成员类,作用域成员枚举,静态数据成员,成员模板和 friends ;
因此,在#3,auto call(state<N>)
仅被声明。而且,通过普通的非限定名称查找找不到此声明。
尽管如此,我认为这不会使您的代码形式上不正确。您的代码太奇怪了,以至于标准委托方成员或编译器实现者可能从未考虑过这种情况:通常在类中定义了内联好友函数,该类使该好友函数可通过ADL(自变量依赖名称查找)可见。当然,这也是编译器所期望的。
因此,在call(state<0>{})
内的main
处,ADL在call
的定义内找到了state
的声明,并且编译器只是不考虑寻找一个某种无关的类add_state
中此函数的潜在定义。因此无法推论auto
。
答案 1 :(得分:0)
我对这件事不太自信,但是希望这可以证明是有用的,我提出了另一个可行的例子,除了已经建议的例子:
#include <iostream>
// forward declaration of the
// add_state template
template<int>
struct add_state;
template<int N>
struct state {
// Note: we generate the state here
// so that the compiler will see the
// definition of the call function
add_state<N> t;
friend auto call(state<N>);
};
template<int N>
struct add_state {
friend auto call(state<N>) {
return N;
}
};
int main() {
auto val = call(state<42>{});
std::cout << val << std::endl;
return 0;
}
我不确定这是否有帮助。但是我希望如此,就像我一样,对一个好的解释感兴趣。
答案 2 :(得分:0)
您的问题在这里:
shopt -s nullglob
files=( /home/methuselah/$filePattern )
for file in "${files[@]}"; do
# something to be done here
done
编译器绝对无法告知template<int N>
struct state {
friend auto call(state<N>);//<--no way of telling return type !
};
函数返回什么并且必须放弃。
该修复程序也很明显,只需对其进行一些操作即可,例如:
call
答案 3 :(得分:-2)
如果使用int
而不是auto
出现错误:
main.cpp:15: undefined reference to `call(state<0>)'
collect2.exe: error: ld returned 1 exit status
将{return N;}
添加到friend int call(state<N>)
时,效果很好。
然后将int
换回auto
,它也可以工作。