在模板,在那里,为什么我必须把typename
和template
上依赖的名字呢?究竟什么是依赖名称?我有以下代码:
template <typename T, typename Tail> // Tail will be a UnionNode too.
struct UnionNode : public Tail {
// ...
template<typename U> struct inUnion {
// Q: where to add typename/template here?
typedef Tail::inUnion<U> dummy;
};
template< > struct inUnion<T> {
};
};
template <typename T> // For the last node Tn.
struct UnionNode<T, void> {
// ...
template<typename U> struct inUnion {
char fail[ -2 + (sizeof(U)%2) ]; // Cannot be instantiated for any …
Run Code Online (Sandbox Code Playgroud) 代码使用GCC编译.这项工作在VC++中没有任何错误
template <typename T>
void Function(T& A){
T::iterator it; //Error : dependent-name 'T::iterator' is parsed as a non-type,
//but instatiation yields a type.
}
Run Code Online (Sandbox Code Playgroud)
本文指出编译器无法弄清楚T
类型中的迭代器是类还是静态成员.因此,我们必须使用typename
关键字将符号分类为类型.
我的问题是,因为T
在编译时已知,然后编译器已经知道iterator
T内部是一个类(在我的例子中是T vector<int>
).那么为什么会有错误呢?
这也是typename
关键字的另一种用途,旁边使用它来定义模板参数T
.
更新:
我从这里读了所有答案和其他答案,真正回答了我的所有想法.我可以总结一下:
处理这个权利的正确编译器是Gcc.VC++将允许您编译格式错误的代码.使用Gcc编译时产生的错误是由于语法分析,因为Gcc将尝试解析函数模板的代码,但它会发现语法错误,这是T::iterator it;
因为Deafault的Gcc将其T::iterator
视为变量(T::iterator
被解析为非变量)为了解决这个问题,你必须明确告诉Gcc将其T::iterator
视为一种类型,这是通过添加关键字来完成的typename
.
现在回到VC++.为什么这有效的答案是因为VC++中存在的错误,VC++是否会延迟决定T::iterator
是变量还是类型.或VC++提供typename
它认为必要的关键字.
有用的文章
注意:如果您发现不正确的内容,请随意编辑更新.
我正在阅读有关typename
C ++模板编程中用法的信息(例如,此Q / A)。对我来说,似乎在使用依赖的嵌套类型名称时,应该使用typename
以避免解析歧义。我还在Scot Meyers的有效C ++书籍#42中对此进行了检查。
但令我感到奇怪的是,书中的相同示例在没有的情况下可以正常工作typename
。这是代码:
template<class C>
void Print2nd(const C & cont)
{
if (cont.size() >= 2)
{
C::const_iterator * iter1 = new C::const_iterator(cont.begin()); // why typename is NOT needed?
C::const_iterator iter2 = cont.begin(); // why typename is NOT needed?
(*iter1)++;
iter2++;
int value1 = **iter1;
int value2 = *iter2;
std::cout << "The value of 2nd with pointer is: " << value1 << std::endl;
std::cout << …
Run Code Online (Sandbox Code Playgroud) 我有一个函数,它接收一个字符列表并生成下一个字典排列.为了好玩,我尝试将代码概括为使用迭代器,以及能够生成更多不同类型的排列.
template<typename ITER>
bool nextPermutation(ITER start, ITER end, std::random_access_iterator_tag)
{
for(ITER i = end-1; i != start; --i)
{
if(*(i-1) < *i)
{
// found where can be swapped
for(ITER j = end-1; j != (i-1); --j)
{
if(*(i-1) < *j)
{
// found what to swap with
auto temp = *j;
*j = *(i-1);
*(i-1) = temp;
// put everything from i on into "sorted" order by reversing
for(ITER k = end-1; k > i; --k,++i)
{
temp = …
Run Code Online (Sandbox Code Playgroud)