I'm trying to implement the pointer to implementation pattern with template classes, and, in order to make independent class and its implementation, I use the next approach:
template<typename T>
struct __A_impl;
template<typename T>
struct A
{
using __impl_t = __A_impl<T>;
A(__impl_t* t);
__impl_t* _t;
};
template<typename T>
struct B
{
T _t;
};
template<typename T>
using __A_impl = B<T>;
With this form, if I want to change the name of 'B', this doens't affect in any way the definition of A. But, I receive the next error with gcc:
test.cpp:21:22: error: declaration of template 'template<class T> using __A_impl = B<T>'
test.cpp:2:7: error: conflicts with previous declaration 'template<class T> class __A_impl'
test.cpp:21:22: error: redeclaration of 'template<class T> using __A_impl = B<T>'
test.cpp:2:7: note: previous declaration 'template<class T> class __A_impl'
How can I achieve this? Because with a typedef declarator isn't possible.
You cannot forward declare a typedef. You can only forward declare classes/structs/enums.
Also, PIMPL is usually used to prevent the compiler from seeing the implementation, but in your case that's never going to happen because it's a template, so I don't see the point.
Well, this compiles, although it might not be what you want:
template<typename T>
struct B
{
T _t;
};
template<typename T>
using __A_impl = B<T>;
template<typename T>
struct A
{
using __impl_t = __A_impl<T>;
A(__impl_t* t);
__impl_t* _t;
};
Anyway, two things:
Why not just use std::unique_ptr?
Double underscores are reserved for implementation. Don't use them.
Related
I have used the std::enable_if metafunction in my class template to specify that it is only allowed to generate classes for variables that have GameCard as a base class. This works fine on its own when I implement the functions inline. However, if I want to implement the template functions outside the header body I run into the issue that I can't figure out how to correctly specify the function that I want to implement.
Cut down example code:
#include <string>
#include <memory>
#include <vector>
struct GameCard {};
template<class T, class = std::enable_if_t<std::is_base_of<GameCard, T>::value>>
struct CardStack {
std::vector<T> cards;
bool Test();
};
My IDE generates this as the function specification:
template<class T, class>
bool CardStack<T, <unnamed>>::Test() {
return false;
}
This is obviously wrong since I'm getting compiler errors. But I don't have a clue on how to do it right. Do any of you know how to do this right?
Out of class definition should be:
template<class T, class Enabler>
bool CardStack<T, Enabler>::Test() {
return false;
}
But currently, you class might be hijacked:
Whereas CardStack<int> or CardStack<int, void> won't compile thanks to SFINAE,
CardStack<int, char> would be "valid" (risk to not compile because of hard error produced by int in CardStack implementation).
static_assert seems enough in your case:
template<class T>
struct CardStack {
static_assert(std::is_base_of<GameCard, T>::value);
std::vector<T> cards;
bool Test();
};
With simpler out of class definition:
template<class T>
bool CardStack<T>::Test() {
return false;
}
The function member definition should be something like:
template <class T, class U>
bool CardStack<T, U>::Test() {
// body of function
}
Live example
The explanation is pretty straightforward, there is no back magic here.
Just follow the normal syntactic rules of C++.
The definition of your class is a template class with two template parameters:
template<class, class>
struct CardStack { /* ... */ };
T is the name of the first one.
On the other hand, the second does not have any type-name, but only a default type (= ...).
Default type (similarly to default arguments for functions) does not have to be specified in the definition.
Therefore, the each method definition should be in the form:
template <class T, class U>
bool CardStack<T, U>::MethodName() {}
I have come across such syntax:
template<typename>
struct is_const{static const bool value = 0;};
How will this code behave and how could it be applied? I didn't find any example or explanation in the Internet.
I am wondering about lack of the argument name (e.g. T).
This is a primary template which takes a single template argument and has a static bool member equal to 0. It is likely that this is the primary template definition for a type trait and that there is a corresponding specialization elsewhere which looks like this:
template <typename T>
struct is_const<const T>
{static const bool value = 1;};
This would allow you to check if a type is const qualified like so:
static_assert(!is_const<int>::value, "wat");
static_assert(is_const<const int>::value, "wat");
template <typename T>
class SampleClass
{
public:
T values [2];
SampleClass(T first, T second)
{
values[0]=first;
values[1]=second;
}
};
Try Something like this typename are generic way of programming. search for generic programming c++. You will get alot of resources
On a basic level of explanation, each time the template is used the compiler generates a version of the templated struct, class, function, etc.
for example:
template<typename T>
struct StructName
{
T memberVariable;
};
when this code is used:
StructName<float> variable = StructName<float>();
the compiler generates:
struct StructName
{
float memberVariable;
};
you can read more about this here: https://en.wikipedia.org/wiki/Template_metaprogramming
I'm trying to compile following code :
#include <iostream>
template<class T> struct Container1;//forward declaration
template<class T> struct Container2;//forward declaration
template<class Container,class Type>
using _Make_Container=typename Container<Type>;
template<class T>
struct Container1
{};
template<class T>
struct Container2
{};
int main()
{
_Make_Container<Container1,int> a;
}
Which give me some errors:
expected nested-name-specifier before 'Container'
using _Make_Container=typename Container<Type>;
^
error: 'Container' is not a template
It seems OK to me because we send Container1 and int to using Then it becomes :
using _Make_Container=typename Container1<int>;
//then
Container1<int> a;
I can't understand the reason for that errors !! Any idea?
Is there any way for making that works ?
Those error messages are pretty clear.
expected nested-name-specifier before 'Container'
using _Make_Container=typename Container<Type>;
^
You're not referring to a nested dependent type so there's no need for the typename keyword here. Read this for a detailed explanation on where typename is required.
error: 'Container' is not a template
Just like it says, your alias template doesn't indicate Container is a template, but then it proceeds to use it as one. You need to use a template template parameter for Container
template<template<typename> class Container,class Type>
using _Make_Container = Container<Type>;
And borrowing Yakk's excellent suggestion, you should change the alias template definition to
template<template <typename...> class T1, typename... T2>
using Make_Container = T1<T2...>;
This lets you do the following:
template<class T, class T1>
struct Container2
{};
Make_Container<Container2,int,long> b;
Finally, names using a leading underscore followed by an upper case letter are reserved by the implementation. So you should rename _Make_Container to Make_Container.
You have to write the alias template like this
template<template <typename> class T1,class T2>
using _Make_Container= T1<T2>;
template< template <class> class Container,class Type>
using _Make_Container = Container<Type>;
Problem
Consider the following class
template <typename T>
struct A
{
T x;
};
Now, another class is templated like so:
template <typename T, typename U>
class B
{
protected:
std::vector<U> arr;
public:
T get_x(unsigned int p) { return arr[p].x; }
};
I would like to access the field A<T>::x from within B<T, A<T>>::get_x() and return it unaltered (i.e., keep its type as T). My poor knowledge of templating says that this requires knowing the type andof T it should be one of the template parameters of class B. However, that makes it possible to declare something inconsistent, like B<int, A<double>>, and in general sounds like an unnecessary repetition.
Questions
Is what I wrote an example of bad programming practice? How should this be written?
Is there a possibility of inferring the type T of A<T>::x and avoid two template types? It feels like a repetition, so I am not sure if there is a God-fearing, standard-abiding solution out there or not.
For what it is worth, I am using GCC 4.6.2 with -std=c++0x.
I would suggest an approach adopted by the Standard Library. Define a nested type.
template <typename T>
struct A
{
typedef T value_type; //this is nested type to be used by B
T x;
};
//this is another class added by me, just to demonstrate the genericity
template <typename T>
struct C
{
typedef T value_type; //this is nested type to be used by B
T x;
};
template <typename T>
class B
{
typedef typename T::value_type value_type; //get the nested type
protected:
std::vector<T> arr;
public:
value_type get_x(unsigned int p) { return arr[p].x; }
//^^^^^^^^^ note this
};
Usage:
B<A<int>> ba; //'>>' if C++11, otherwise use '> >' (separate them by space)
B<C<double>> bc; //works for C class template as well
Which is more correct? And Why.
On work I recently run in a discussion how to do a specific template specialization.
This way:
template <typename T, bool someBoolVar = is_polymorphic<T>::value>
struct SomeTemplate { // with empty definition
};
template <typename T>
struct SomeTemplate<T, true> {
...
};
template <typename T>
struct SomeTemplate<T, false> {
...
};
or this way:
template <typename T, bool someBoolVar = is_polymorphic<T>::value>
struct SomeTemplate; // without empty definition -- difference here
template <typename T>
struct SomeTemplate<T, true> {
...
};
template <typename T>
struct SomeTemplate<T, false> {
...
};
Neither. Because both will not compile! Wrong syntax for partial specialization!
This is how partial specialization is done:
//correct syntax
template <typename T>
struct SomeTemplate<T,false> {
...
};
Not this:
//wrong syntax
template <typename T, false>
struct SomeTemplate {
...
};
Now answer to your question assuming you'll fix the syntax!
In my opinion, the second approach is rational, because bool can have ONLY two values, so three versions of SomeTemplate class template doesn't make sense at all, which you're doing in the first approach.
The second way will generate a compiler error if you try to use the template in a way that isn't specialized. The first way just gives you an empty class in those cases, which may or may not generate an error later on when you try to use the class.
The kicker here is that there are only two values for bool and you've specialized for both, so it really doesn't matter which way you go. The empty class won't be linked and thus doesn't generate any extra code.
This specific case is like the compile-time-assertion pattern:
template<bool test> struct compiler_assert;
template<> struct compiler_assert<true> {};
// ...
compiler_assert<bool_test_goes_here> assert1;
Which stops the compile if the test evaluates to false.
Both examples have syntax errors. Assuming you fix them, there isn't any difference between the two. Empty implementation, which you provided in the first example can never be used, so no code generated.