Using a template structure as a namespace - c++

I just finished an iteration on a library that I am writing.
In order to isolate certain types, I originally put them into a namespace.
Then, I realised that this namespace should actually be templated, so I turned it into a struct, ie:
namespace A
{
typedef _foo foo;
}
became
template <class T>
struct A
{
typedef _foo<T> foo;
};
This was more convenient to use in say, this situation:
template <class T>
class MyClass
{
public:
typedef A<T> nsA;
typedef typename nsA::foo foo_type;
};
Now, I'm using that library in another library, and there, I know that the template type T will never change. So I would like to do something like:
namespace B
{
using namespace A<double>;
}
but obviously, this doesn't work. Of course, I could just stop being lazy, and typedef manually each definition in A<double>, but I like being lazy when I can. Any thoughts on how to do something equivalent to this last step?

Actually, I just found the answer. Sorry, if you think this question was useless, I'll delete it, just let me know in comment.
Since I used a struct as a namespace in the first place, the solution is to keep using a struct as a namespace (!):
struct B
: public A<double>
{};
Here is a demo.

Related

How do I do a forward declaration of a struct with a typename?

I am trying to do a forward declaration of a struct in c++ that has a typename. Something like this is entirely valid:
typedef struct foo foo;
struct foo{
int f;
};
My struct just instead has a typename, so I tried this:
template <typename T>
typedef struct mV<T> mV;
template <typename T>
struct mV{
//contents of struct
};
However, I then get the errors a typedef cannot be a template, explicit specialization of undeclared template struct and redefinition of 'mV' as different kind of symbol. How can I go about fixing that?
You're describing a forward- declaration . (A future is something completely different in modern C++).
typedef aliasing structure tags is not needed, and rarely desired, in C++. Instead you simply declare the class type and be done with it.
// typedef struct mV mV; // not this
struct mV; // instead this
The same goes for templates
template<class T>
struct mV;
If you need/want to attach an alias to your template type, you still can do so via using
template<class T>
struct mV;
template<class T>
using MyAliasNameHere = mV<T>;
Armed with all of that, and heading off what I surmise you'll be discovering in short order, you'll probably need to read this as well: Why can templates only be implemented in header files?. Something tells me that's about to become highly relevant.

traits class, namespace and forward declaration

I am currently having trouble using namespaces with traits classes. Here is my tentative code structure:
namespace project {
namespace internal {
template<typename T> struct traits;
} // internal
namespace moduleA {
namespace internal {
class AImpl {
using some_typeA = traits<A>::some_type;
using some_typeAImpl = traits<AImpl>::some_type;
// where to put the traits specialization?? How the forward declaration could be done?
};
} // internal
class A {
A(): imp(new internal::AImpl()) {}
private:
internal::AImpl* imp;
};
} // moduleA
} // project
Here are my questions and I am looking for suggestions to make this code better follow the established conventions and best practices:
I am defining two internal namespaces, ::project::internal and ::project::moduleA::internal, is this a bad practice? My concern on this is that with two levels it might be easier for user to browse the documentation from doxygen, as all the moduleA related stuff, both moduleA::internal and not, are grouped together.
Because moduleA::internal::AImpl depends on the traits class of itself traits<AImpl>, and my traits templates resides in ::project::internal, so I have to either (1) define a traits template in moduleA::internal and specialize it; (2) define the traits specialization in ::project::internal. For this, I'll need forward-declare AImpl. How exactly should it be done for each of the case (1) or (2)? Does that mean I have to write code like this:
namespace project {
namespace moduleA {class A;}
namespace internal {
template<>
struct traits<module::A> {};
}
namespace moduleA {
... // more code
}
}
It looks like I am making too much use of namespace {} clauses.
Similar to 2, module::internal::AImpl depends on traits<A>, again I need to forward declare A, so the same problem.
I'd greatly appreciate you help on this, thank you!
Instead of using class templates for traits in C++11 you can use function declarations (no definition is necessary). Functions can be found using argument-dependent name lookup, so that you can specialise traits for your class in the same namespace where your class is declared.
This completely removes the nuisance of having to close the namespace of your class, open the traits namespace, specialise the trait for your class using its fully qualified name, close the traits namespace, re-open the namespace of your class. And also removes the need to include the declaration of the primary template.
Example:
#include <type_traits>
template<class T> struct Type {};
template<class T>
void trait_of(Type<T>); // Generic trait version.
namespace N {
struct A;
int trait_of(Type<A>); // Trait specialisation for A.
} // N
int main() {
using trait_of_a = decltype(trait_of(Type<N::A>{})); // trait_of is found using ADL.
static_assert(std::is_same<int, trait_of_a>::value, "");
}
The return type of the trait function can be a container of more types, e.g.:
template<class T>
void more_traits(Type<T>); // Generic trait version. Must be specialized.
namespace N {
struct MoreTraitsOfA {
using type_X = ...;
using type_Y = ...;
};
MoreTraitsOfA more_traits(Type<A>); // Trait specialisation for A.
} // N
using MoreTraits = decltype(more_traits(Type<N::A>{}));
using type_X = MoreTraits::type_X;
using type_Y = MoreTraits::type_Y;

Simulating argument-dependent lookup for template arguments

I've encountered this problem while writing some library-like code recently, and I thought discussing it might help others as well.
Suppose I have a library with some function templates defined in a namespace. The function templates work on types supplied by client code, and their inner workings can be customized based on type traits defined for the client types. All client definitions are in other namespaces.
For the simplest example possible, a library function would basically have to look like this (note that all the code snippets are just wishful thinking, nothing compiles):
namespace lib
{
template<typename T> void f()
{
std::cout << traits_for<T>::str() << '\n'; //Use the traits in some way.
}
}
Client code would look like this:
namespace client
{
struct A { };
template<> std::string traits_for<A>::str() { return "trait value"; }
}
And then someone, somewhere could call
lib::f<client::A>();
and everything would magically work (the specialization of lib::f() would find the traits explicit specialization in the namespace where the template argument for T is declared, just like ADL does for functions and their arguments). The goal is to make it as easy as possible for client code to define those traits (there could be several) for each client class (there could be lots of those).
Let's see what we could do to make this work. The obvious thing is to define a traits class primary template in lib, and then explicitly specialize it for client types. But then clients can't define those explicit specializations in their own namespace; they have to exit it, at least up to the global namespace, define the explicit specialization, then re-enter the client namespace, which, for maximum fun, could be nested. I'd like to keep the trait definitions close to each client class definition, so this namespace juggling would have to be done near each class definition. Suddenly, a one-liner in client code has turned into a messy several-liner; not good.
To allow the traits to be defined in the client namespace, we could turn the traits class into a traits function, that could be called from lib like this:
traits_for(T())
but now we're creating an object of class T just to make ADL kick in. Such objects could be expensive to construct (or even impossible in some circumstances), so this isn't good either. We have to keep working with types only, not their instances.
Giving up and defining the traits as members of the client classes is not an option either.
Some plumbing required to make this work would be acceptable, as long as it doesn't complicate the definitions for each class and trait in the client namespace (write some code once, but not for every definition).
I've found a solution that satisfies these stringent requirements, and I'll write it up in an answer, but I'd like to find out what people think about this: alternatives, critique of my solution, comments about how all of this is either bleeding obvious or completely useless in practice, the works...
To find a declaration based on some argument, ADL looks like the most promising direction. So, we'll have to use something like
template<typename T> ??? traits_helper(T);
But we can't create objects of type T, so this function should only appear as an unevaluated operand; decltype springs to mind. Ideally, we shouldn't even assume anything about T's constructors, so std::declval could also be useful:
decltype(traits_helper(std::declval<T>()))
What could this do? Well, it could return the actual traits type if the helper would be declared like this:
template<typename T> traits_for<T> traits_helper(T);
We've just found a class template specialization in another namespace, based on the declaration of its argument.
EDIT: Based on a comment from Yakk, traits_helper() should take a T&&, to allow it to work if T's move constructor is not available (the function may not actually be called, but the semantic constraints required for calling it must be met). This is reflected in the complete sample below.
All put together in a standalone example, it looks like this:
#include <iostream>
#include <string>
#include <utility>
namespace lib
{
//Make the syntax nicer for library code.
template<typename T> using traits_for = decltype(traits_helper(std::declval<T>()));
template<typename T> void f()
{
std::cout << traits_for<T>::str() << '\n';
}
}
namespace client_1
{
//The following two lines are needed only once in every client namespace.
template<typename> struct traits_for { static std::string str(); };
template<typename T> traits_for<T> traits_helper(T&&); //No definition needed.
struct A { };
template<> std::string traits_for<A>::str() { return "trait value for client_1::A"; }
struct B { };
template<> std::string traits_for<B>::str() { return "trait value for client_1::B"; }
}
namespace client_2
{
//The following two lines are needed only once in every client namespace.
template<typename> struct traits_for { static std::string str(); };
template<typename T> traits_for<T> traits_helper(T&&); //No definition needed.
struct A { };
template<> std::string traits_for<A>::str() { return "trait value for client_2::A"; }
}
int main()
{
lib::f<client_1::A>(); //Prints 'trait value for client_1::A'.
lib::f<client_1::B>(); //Prints 'trait value for client_1::B'.
lib::f<client_2::A>(); //Prints 'trait value for client_2::A'.
}
Note that no objects of type T or traits_for<T> are created; the traits_helper specialization is never called - only its declaration is used.
What's wrong with just requiring clients to throw their specializations in the right namespace? If they want to use their own, they can:
namespace client
{
struct A { };
struct traits_for_A {
static std::string str() { return "trait value"; }
};
}
namespace lib
{
template <>
struct traits_for<client::A>
: client::traits_for_A
{ };
}
Could even give your users a macro if you don't want them to write all that out:
#define PROVIDE_TRAITS_FOR(cls, traits) \
namespace lib { \
template <> struct traits_for<cls> : traits { }; \
}
So the above can become
PROVIDE_TRAITS_FOR(client::A, client::traits_for_A)
ADL is awesome. Keep it simple:
namespace lib {
// helpers for client code:
template<class T>
struct default_traits{
using some_type=void;
};
struct no_traits{};
namespace details {
template<class T,class=void>
struct traits:lib::no_traits{};
template<class T>
struct traits<T,decltype(void(
traits_func((T*)0)
))>:decltype(
traits_func((T*)0)
){};
}
template<class T>
struct traits:details::traits<T>{};
}
Now simply add in the type Foo namespace:
namespace bob{
// use custom traits impl:
struct foo{};
struct foo_traits{
using some_type=int;
};
foo_traits traits_func(foo const*);
// use default traits impl:
struct bar {};
lib::default_traits<bar> traits_func(bar const*);
// use SFINAE test for any type `T`:
struct baz {};
template<class T>
std::enable_if_t<
std::is_base_of<T,baz>{},
lib::default_traits<T>
>
traits_func(T const*)
}
and we are done. Defining traits_func that takes a pointer convertable from foo* is enough to inject the trait.
If you fail to write such an overload, we get an empty traits, which is SFINAE friendly.
You can return lib::no_traits in an overload to explicitly turn off support, or just don;t write an overload that matches a type.

C++ Forward declare using directive

I have a header which exposes a templated class and a typedef via using, something like:
namespace fancy {
struct Bar {
...
}
template<typename T>
class Foo {
...
}
using FooBar = Foo<Bar>;
}
I would like to forward declare FooBar to use it in a shared_ptr in another header. I've tried
namespace fancy {
using FooBar;
}
like for a class or struct, but without luck. Is this possible, and if so, how?
You can't declare a using alias without defining it. You can declare your class template without defining it, however, and use a duplicate using alias:
namespace fancy {
template <typename> class Foo;
class Bar;
using FooBar = Foo<Bar>;
}
Another way to use forward declare is to replace using with the class inheritance:
// using FooBar = Foo<Bar>;
class FooBar : public Foo<Bar> {};
Of course, now FooBar is not the same thing as Foo<Bar>. For instance, you need to inherit possibly existente constructors via using Foo<Bar>::Foo, but as a profit you can use easy forward declare as usual. Just:
namespace fancy {
class FooBar;
}
If your using declaration is too large (a lot of template parameters, which on their turn are also defined by a using statement), you could also add a dummy forward struct that has the using type as a dependent type:
namespace fancy {
struct Bar {
...
}
template<typename T>
class Foo {
...
}
using FooBar = Foo<Bar>;
// Forward struct
struct FooBarFwd {
using type = FooBar;
}
}
Then in your place where you want to forward declare:
namespace fancy {
class FooBarFwd;
}
// use your type as
typename FooBarFwd::type baz(const typename FooBarFwd::type & myFooBar);
// instead of
// FooBar baz(const FooBar & myFooBar);
Some disadvantages of this approach are
Using typename to disambiguate the dependent type.
Extra indirection for your type, some compilers could have problems when reporting errors.
Changing to this approach might need quite a lot of changes to your code (changing every occurence of FooBar with typename FooBarFw::type)
Therefore, I advise to apply this technique only when you are certain what you are doing.

How to access hidden template in unnamed namespace?

Here is a tricky situation, and i wonder what ways there are to solve it
namespace {
template <class T>
struct Template { /* ... */ };
}
typedef Template<int> Template;
Sadly, the Template typedef interferes with the Template template in the unnamed namespace. When you try to do Template<float> in the global scope, the compiler raises an ambiguity error between the template name and the typedef name.
You don't have control over either the template name or the typedef-name. Now I want to know whether it is possible to:
Create an object of the typedefed type Template (i.e Template<int>) in the global namespace.
Create an object of the type Template<float> in the global namespace.
You are not allowed to add anything to the unnamed namespace. Everything should be done in the global namespace.
This is out of curiosity because i was wondering what tricks there are for solving such an ambiguity. It's not a practical problem i hit during daily programming.
I know it somewhat spoils your point, but I really think the main trick is to avoid something like this like the plague.
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 that yields
void PrintType() [with T = <unnamed>::Template<int>]
void PrintType() [with T = <unnamed>::Template<float>]
Apparently it compiles with Cormeau, but I only have access to their online test, so I'm stuck just assuming it functions as expected.
I couldn't figure out any way to pass an actual type to a struct directly and have it degrade into a template type, but the compiler had no problems stripping the two when it had to guess at function parameters. Maybe this works in C++03 using boost::result_of instead of decltype, but I've never used it before so I figured I'd stick to what I know.
Note the spacing within main. Rebind<::Template, float>::NewType gets gobbled by the parser because of <: being a digraph. I think it gets turned into Rebind[:Template, float>::NewType. So the space before ::Template is vital.
As an aside, I had no idea nested template parameters couldn't use typename [template<template<typename> class T> rather than template<template<typename> typename T>]. I think I relearn that every time I try to remember the syntax for the construct.
It's possible to access the global typedefed template by being explicit about the namespace, ie
::Template a
is a Template<int> from the anonymous namespace. Not sure if you can get a Template<float>.
Surprisingly Clang's C++ compiler is fine with the following, probably not standard behaviour:
#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";
}
disclaimer: I don't know why you'd want to do this and would probably speak sternly to someone who did.
namespace
{
template <typename T> class Template { };
}
typedef Template<int> IntTemplate;
typedef Template<float> FloatTemplate;
typedef IntTemplate Template;
int main() {
::Template t;
FloatTemplate ft;
}