"无效类型的使用无效"使用模板化类型和命名空间

时间:2015-08-15 03:21:53

标签: c++ templates c++11 namespaces

以下是我在std::tuple上使用的迭代器的简化。在其中,我在一个名称空间中定义模板化类型,并在第二个名称空间中使用它,如下所示:

namespace meta{
    template<size_t> struct meta_size_t {};     
}

namespace ns{

    //template<size_t> struct ns_size_t {};     

    template <size_t N> 
    void bar(meta::meta_size_t<N>) { 
        bar(meta::meta_size_t<N-1>()); 
    }
    void bar(meta::meta_size_t<1>) {}

    template<size_t N> 
    void foo() { 
        bar(meta::meta_size_t<N>()); 
    }
}

int main(void){
    ns::foo<5>();   
    return 0;
}

代码在MSVC2015中编译良好,但在g ++ 4.8和clang 3.5(-std = c ++ 11)中失败,达到模板的最大递归深度。请注意,如果meta::meta_size_t替换为ns_size_t(并且ns_size_t的定义已取消注释),那么一切正常。

我猜测编译器会延迟meta::meta_size_t的分辨率,直到它完成解析bar,因为它在另一个命名空间(或沿着这些行的某些东西),并且是因此失败了,但我不确定如何解决这个问题。

在什么条件下这个问题通常会出现?有没有办法迫使编译器在namespace meta's之前解析ns's内容?我希望避免重复类型定义(如ns_size_t所示)。

进一步背景:在原始代码中,bar有一个std::tuple参数,并使用std::get<N>(tuple)

调用重载函数

编辑: Noobish错误。在查看了@WhozCraig提供的示例之后,我验证了代码可以通过交换两个bar方法的顺序来修复(我假设g ++和clang按顺序搜索定义,因此永远不会注册bar的第二次重载,而MSVC必须在继续之前将所有定义添加到其符号表中。标准是指定一种方法还是另一种方法,或者该实现是否具体?也就是说,如果定义不在命名空间内,我不明白为什么这不是问题。

0 个答案:

没有答案