2010-05-28 156 views
4

这是一个棘手的情况,我不知道什么样的方式有解决它如何访问匿名命名空间中的隐藏模板?

namespace { 
    template <class T> 
    struct Template { /* ... */ }; 
} 

typedef Template<int> Template; 

可悲的是,Template的typedef在无名命名空间中的Template模板干扰。当您尝试在全局范围内执行​​时,编译器会在模板名称和typedef名称之间产生歧义错误。

您无法控制模板名称或typedef名称。现在,我想知道是否有可能:

  • 创建全局命名空间中通过typedef类型Template(即Template<int>)的对象。
  • 在全局名称空间中创建类型为​​的对象。

您是不是允许向未命名的命名空间添加任何内容。一切都应该在全局命名空间中完成。

这是出于好奇心,因为我想知道有什么技巧可以解决这种歧义。这不是我在日常编程中遇到的实际问题。

+0

我使它成为社区维基,因为它实际上是一个有趣的好奇问题,而不是实际的东西。 :) – 2010-05-28 21:29:46

+0

请注意,有*是*至少一个解决方案的第二个问题,编译所有ng/gcc/comeau,但它只是更难以发现:) – 2010-05-28 22:09:27

+0

我没有时间充分考虑这一点,但是不要使用分配器来改变模板参数吗?你能不能在这里做类似的事情,并且最终得到一些类似于'Rebind <:: Template,float> :: type'的东西?这样,'Template'将被重新命名,在'Rebind'中被称为'T',并且没有歧义。 – 2010-05-28 22:26:14

回答

0

我知道这有点破坏你的观点,但我真的认为主要的诀窍是避免像瘟疫一样的东西。

0

它可以通过显式说明的命名空间访问全局typedef操作模板,即

::Template a 

是匿名命名空间的Template<int>。不知道你是否可以得到​​。

令人惊讶Clang的C++编译器是细跟以下,可能不是标准的行为:

#include <iostream> 
namespace { 
    template <class T> 
     struct Template {T value;};} 
typedef Template<int> Template; 

int main(){  
    ::Template a; 
    Template<float> b; 
    a.value = 6; 
    b.value = 3.14; 
    std::cout<<a.value<<" "<<b.value<<"\n"; 
} 
+0

是的,铛是不正确的接受。 Comeau和GCC也禁止:)好的发现,你会报告还是应该这样做? – 2010-05-28 21:48:12

+0

我已经减少到这个测试用例:http://codepad.org/pnrSlhPq – 2010-05-28 21:54:31

+0

@Johannes谢谢,报告为http://llvm.org/bugs/show_bug.cgi?id=7251 – 2010-05-28 23:53:28

-1

免责声明:我不知道为什么你要做到这一点,可能会严厉地与别人交谈谁干的。

namespace 
{ 
    template <typename T> class Template { }; 
} 

typedef Template<int> IntTemplate; 
typedef Template<float> FloatTemplate; 
typedef IntTemplate Template; 

int main() { 
    ::Template t; 
    FloatTemplate ft; 
} 
+0

嗯,'typedef模板模板;'在你的回答中不知何故:)它意味着一块。事实之后应该添加一切。这就是为什么它是如此难以做:) – 2010-05-28 21:46:27

+0

哦,我认为需求只是在命名空间内的东西不能改变。基本上,无论你想要做什么都是不正确的。隐藏“内部”事物并没有任何意义,然后尝试同时提供新旧定义。 – 2010-05-28 22:09:22

1

使用的C++ 0x:

namespace { 
    template<class T> struct Template { }; 
} 
typedef Template<int> Template; 

#include<iostream> 

template<typename T> 
void PrintType() { 
    std::cout << __PRETTY_FUNCTION__ << std::endl; 
} 

template<typename FullType, typename NewParameter> 
class Rebind { 
    template<template<class> class Template, typename OldParameter> 
    static Template<NewParameter> function(Template<OldParameter>); 

public: 
    typedef decltype(function(FullType())) NewType; 
}; 

int main() 
{ 
    PrintType< ::Template>(); 
    PrintType<Rebind< ::Template, float>::NewType>(); 
    return 0; 
} 

随着gcc45能产生

void PrintType() [with T = <unnamed>::Template<int>] 
void PrintType() [with T = <unnamed>::Template<float>] 

显然,这与编译Cormeau,但我只能访问他们的在线测试,所以我米坚持假设其功能如预期。

我找不出任何方法直接将实际类型传递给结构,并将其降级为模板类型,但编译器在必须猜测函数参数时没有问题。也许这在C + + 03中使用boost::result_of而不是decltype,但我以前从未使用它,所以我想我会坚持我所知道的。

请注意main内的间距。由于<:是有向图,Rebind<::Template, float>::NewType被解析器吞噬。我认为它变成了Rebind[:Template, float>::NewType。所以::Template之前的空间是至关重要的。另外,我不知道嵌套的模板参数不能使用typename [template<template<typename> class T>而不是template<template<typename> typename T>]。我想我每次尝试记住构造的语法时都会重新学习一下。

+0

啊你的答案让我想到了第二种方法来解决这个问题在C + + 03。你正在用第二种方式来解决它,实际上...... :) – 2010-05-29 11:30:59