How to access a hidden template in an unnamed namespace?

Here is a difficult situation, and I wonder what ways to solve it.

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

Unfortunately, typedef Template interferes with the Template in an unnamed namespace. When you try to execute Template<float> in a global scope, the compiler raises an ambiguity error between the template name and the typedef name.

You have no control over the template name or typedef name. Now I want to know if:

  • Create an object of type typedefed Template (ie Template<int> ) in the global namespace.
  • Create an object of type Template<float> in the global namespace.

You are not allowed to add anything to an unnamed namespace. Everything needs to be done in the global namespace.

This is out of curiosity because I was wondering what tricks exist to solve such ambiguity. This is not a practical problem that I hit during daily programming.

+4
source share
4 answers

Using 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; } 

With gcc45 which gives

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

It seems to be compiling with Cormeau, but I only have access to their online test, so I got stuck believing that it was functioning as expected.

I could not figure out how to pass the actual type into the structure directly and break it down into a template type, but the compiler had no problem decoupling them when it was necessary to guess the parameters of the function. Maybe this works in C ++ 03 using boost::result_of instead of decltype , but I never used it before, so I decided that I would stick to what I know.

Pay attention to the interval between main . Rebind<::Template, float>::NewType gets a gobbled parser because <: is a digraph. I think it turns into Rebind[:Template, float>::NewType . Thus, the space before ::Template vital.

As an aside, I had no idea that the nested template parameters cannot use typename [ template<template<typename> class T> , and not template<template<typename> typename T> ]. I think I'm relearning that every time I try to remember the syntax for a construct.

+1
source

I know this spoils your thoughts somewhat, but I really think the main trick is to avoid something like the plague.

0
source

You can access the global template with a type by explicitly specifying a namespace, i.e.

 ::Template a 

is a Template<int> from an anonymous namespace. Not sure if you can get the Template<float> .

Surprisingly, the Clang C ++ Compiler is fine with the following, possibly non-standard behavior:

 #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
source

Disclaimer: I don’t know why you want to do this and probably speak decisively with the person who did it.

 namespace { template <typename T> class Template { }; } typedef Template<int> IntTemplate; typedef Template<float> FloatTemplate; typedef IntTemplate Template; int main() { ::Template t; FloatTemplate ft; } 
-1
source

Source: https://habr.com/ru/post/1311254/


All Articles