C++ 如何访问未命名命名空间中的隐藏模板?

C++ 如何访问未命名命名空间中的隐藏模板?,c++,templates,names,C++,Templates,Names,这是一个棘手的情况,我想知道有什么办法可以解决它 namespace { template <class T> struct Template { /* ... */ }; } typedef Template<int> Template; 名称空间{ 模板 结构模板{/*…*/}; } typedef模板; 遗憾的是,Templatetypedef会干扰未命名命名空间中的Template模板。当您尝试在全局范围内执行模板时,编译器会在模板名称和type

这是一个棘手的情况,我想知道有什么办法可以解决它

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

typedef Template<int> Template;
名称空间{
模板
结构模板{/*…*/};
}
typedef模板;
遗憾的是,
Template
typedef会干扰未命名命名空间中的
Template
模板。当您尝试在全局范围内执行
模板
时,编译器会在模板名称和typedef名称之间产生歧义错误

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

  • 在全局命名空间中创建类型定义为
    模板
    (即
    模板
    )的对象
  • 在全局命名空间中创建
    模板
    类型的对象
不允许向未命名的命名空间添加任何内容。一切都应该在全局名称空间中完成


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

我知道这有点破坏了你的观点,但我真的认为主要的技巧是避免像瘟疫这样的事情

可以通过明确名称空间来访问全局typedefed模板,即

::Template a
是来自匿名命名空间的
模板。不确定是否可以获得
模板

令人惊讶的是,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";
}
#包括
名称空间{
模板
结构模板{T值;};}
typedef模板;
int main(){
::模板a;
模板b;
a、 数值=6;
b、 数值=3.14;

免责声明:我不知道你为什么要这么做,而且可能会对这么做的人严肃地说

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

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

int main() {
    ::Template t;
    FloatTemplate ft;
}
名称空间
{
模板类模板{};
}
typedef模板IntTemplate;
typedef模板FloatTemplate;
typedef IntTemplate模板;
int main(){
::模板t;
浮动模板ft;
}
使用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;
}
名称空间{
模板结构模板{};
}
typedef模板;
#包括
模板
void PrintType(){
std::cout();
返回0;
}
与gcc45的产量

void PrintType() [with T = <unnamed>::Template<int>]
void PrintType() [with T = <unnamed>::Template<float>]
void PrintType()[带T=::模板]
void PrintType()[带T=::模板]
显然它是用Cormeau编译的,但我只能访问他们的在线测试,所以我只能假设它的功能如预期的那样

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

请注意,
main
Rebind::NewType
中的空格会被解析器占用,因为
::NewType
。因此,
::Template
之前的空格至关重要


顺便说一句,我不知道嵌套模板参数不能使用typename[
template
而不是
template
]。我想每次我试着记住这个结构的语法时,我都会重新认识到这一点。

我把它变成了社区维基,因为这确实是一个有趣的好奇问题,而不是一些实用的问题。:)请注意,对于第二个问题,至少有一个解决方案可以在所有的clang/gcc/comeau上编译,但它更难找到:)我没有时间仔细考虑这一点,但是分配器不是有一些他们用来更改模板参数的诡计吗?你能在这里做一些类似的事情,并最终得到类似于
重新绑定<::模板,浮点>::键入
?这样,
模板
将被重命名,比如
t
Re中绑定
,并且没有歧义。该死,我会解决这个问题…需要我的思维帽,我已经生锈了。嗯,
typedef模板;
在你的答案中不知怎么消失了:)它本来是一个块。所有的东西都应该在事实之后添加。这就是为什么这么难做到:)哦,我以为要求的只是里面的那些东西无法更改e名称空间。基本上,您尝试执行的任何操作都是不正确的。隐藏“内部”名称空间没有任何意义这完全没有意义。这是一个语言律师的问题。它与任何有意义的软件都没有联系:)是的,clang接受这一点是不正确的。Comeau和GCC也禁止:)好发现,你会报告还是我应该报告?既然你在玩语言lawyer,你能找到标准中的引用,它要求这个案例被人为地模糊处理吗?你有一个明确的例子,它不是模糊的,编译器有有效和系统的方法来解决它。因此,如果你确实找到了标准中的引用,那么至少尝试针对标准而不是错误的编译器有效率的解决方案。啊,你的回答让我想到了第二种方法来解决这个问题在C++03。你接近使用第二种方法来解决它,实际上…:)