c++ - "Invalid use of incomplete type"使用模板化类型和命名空间

标签 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 (或类似的东西)中,因此失败了,但我不确定如何解决这个问题。

这个问题一般在什么情况下出现?有没有办法强制编译器解析 namespace meta's ns's之前的内容?我想避免重复类型定义(如 ns_size_t 所示)。

更多上下文:在原始代码中,bar有一个 std::tuple参数,并使用 std::get<N>(tuple) 调用重载函数

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

最佳答案

基本规则是当你写foo(/* something dependent on a template parameter*/); , foo 的普通不合格查找仅考虑模板定义上下文,而 ADL 将同时考虑定义和实例化上下文。因此,要考虑在模板定义上下文中找不到的重载的唯一方法是通过 ADL。

bar(meta::meta_size_t<N-1>()); , void bar(meta::meta_size_t<1>) {}不在范围内,所以调用它的唯一方法是通过参数相关的查找,但是 ns不是 meta::meta_size_t<1> 的关联命名空间,所以你得到的是无限递归。

当您使用 ns_size_t 时, 然后 ns是关联的命名空间,因此 bar 的第二次重载由 ADL 找到并由重载决议选择,终止递归。

当您交换 bar 的顺序时s,那么普通的非限定查找将找到终止案例,所以一切都很好。

MSVC 以其在模板名称查找方面的不规范而闻名。

关于c++ - "Invalid use of incomplete type"使用模板化类型和命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32021189/

相关文章:

c++ - 对不同级别的树使用不同的 C++ 模板

c++ - 访问类/结构范围之外的 protected 成员?

c++11 - Andrei Alexandrescu 关于爆炸元组的演讲中奇怪的 result_of<F(Ts...)>

c++ - 为什么将影响 lambda 的代码编译为 std::function 如此缓慢,尤其是使用 Clang 时?

c++ - clang 能代替 Exuberant Ctags 吗?

c++ - 如何在 Linux 或 Windows 中编译 OS X?

c++ - lcov 问题 : weird duplicate constructor marked as not covered & function not marked as covered, 即使其行已被执行

c++ - 打印任何 vector 的内容

c++ - C++ 中带有换行符的 printf 的奇怪行为

c++ - boost .Python : Ownership of pointer variables