Let's say I have following templated C++ class
#include <cstdint>
template <uint32_t NO_POINTS>
class A
{
public:
struct Point
{
float x;
float y;
};
A(const Point (&points)[NO_POINTS])
{
for (uint32_t point = 0; point < NO_POINTS; point++) {
table[point] = points[point];
}
}
private:
Point table[NO_POINTS];
};
and I would like to use an instance of this class as a private member of the following class:
#include "A.h"
template <uint32_t NO_LUT_POINTS>
class B
{
public:
B(A<NO_LUT_POINTS>::Point (&table)[NO_LUT_POINTS]) : lut(table){}
private:
A<NO_LUT_POINTS> lut;
};
#include "B.h"
int main(int argc, char** argv) {
B<4> foo({{1326.0, 25.0}, {1601.0, 30.0}, {1922.0, 35.0}, {2293.0, 40.0}});
return 0;
}
I have attempted to compile this code but the compiler reports following error
A<NO_LUT_POINTS>::Point is not a type. I don't understand what the reason for this error is. Can anybody explain to me why the compiler reports this error?
This is a common mistake with types nested in template classes. You need to add typename to tell the compiler that Point is a type.
...
public:
B(typename A<NO_LUT_POINTS>::Point const (&table)[NO_LUT_POINTS]) : lut(table){}
...
Beyond solving your problem, however, please notice that Point doesn't depend on the template parameters of A, so you should not nest it in that class. This would remove the necessity for adding typename.
Related
This is about the following setup of an application that uses (abstract) functionality from a *.dll and a static library and which causes read access violation at last (further details are provided below the code):
... static library ...
// InterfaceWrap.h
//-----------
// dummy include
#include <SomeTClass.h>
template<typename T>
class InterfaceWrap
{
std::shared_ptr<SomeTClass<T>> m_somePtr;
public:
InterfaceWrap();
~InterfaceWrap();
void AnyAction();
};
template<typename T>
InterfaceWrap<T>::InterfaceWrap() {
m_somePtr = std::make_shared<SomeTClass<T>>();
}
template<typename T>
void InterfaceWrap<T>::AnyAction() {
m_somePtr->SomeAction();
}
... *.dll ...
// Proc.h
//-----------
// correct forward declaration?
class ThisInterface;
#include <InterfaceWrap.h>
class DLL Proc
{
std::shared_ptr<InterfaceWrap <ThisInterface>> m_interfaceWrapPtr;
public:
Proc();
~Proc();
InterfaceWrap<ThisInterface>* GetPtr();
};
// Proc.cpp
//-----------
// what about forward declaration here?
Proc::Proc() {
m_interfaceWrapPtr = std::make_shared<InterfaceWrap<ThisInterface>>();
}
InterfaceWrap<ThisInterface>* Proc::GetPtr() {
return m_interfaceWrapPtr.get();
}
... the application ...
// main.cpp
//-----------
#include <Proc.h>
// dummy includes
#include <ThisType01.h>
#include <ThisType02.h>
#include <ThisType11.h>
#include <ThisType12.h>
class ThisInterfaceA {
public:
using Type1 = ThisType01;
using Type2 = ThisType02;
};
class ThisInterfaceB { // not needed here but perhaps illustrative
public:
using Type1 = ThisType11;
using Type2 = ThisType12;
};
using ThisInterface = ThisInterfaceA;
int main(int argc, char * argv[])
{
Proc proc;
proc.GetPtr()->AnyAction();
return 0;
}
The crucial intention behind this construction is to keep the Proc and InterfaceWrap classes as abstract as possible, i.e., having them not depending directly on a chosen "interface" like ThisInterfaceA. Moreover I would like to keep the feature, that Proc is not a template class.
Obviously there are problems, of which I'm not sure how to resolve them nicely:
The line using ThisInterface = ThisInterfaceA does not work as it leads to compilation errors for the dll source codes, basically saying that ThisInterface is not known. If however, instead of this line, e.g., ThisInterfaceA is replaced by ThisInterface directly, everything compiles and links fine, at least.
Even if everything compiles and links (compare 1.), there would ultimately occur a read access violation, which concerns m_interfaceWrapPtr or m_somePtr.
What I wonder in particular is, whether properly applied forward declaration is capable of resolving the above issues and allowing to keep the feature that Proc is that abstract (or even more?) and not a template class?
Why not use real interface and DIP:
struct IAnyAction
{
virtual ~IAnyAction() = default;
virtual void AnyAction() = 0;
};
class Proc
{
std::shared_ptr<IAnyAction> m_interface;
public:
Proc(std::shared_ptr<IAnyAction> anyAction) : m_interface(anyAction) {}
IAnyAction* GetPtr() { return m_interface.get(); }
};
template<typename T>
class InterfaceWrap : public IAnyAction
{
std::shared_ptr<SomeTClass<T>> m_somePtr;
public:
InterfaceWrap();
void AnyAction() override { m_somePtr->SomeAction(); }
};
and
using ThisInterface = ThisInterfaceA; // For easy/quick way to change concrete type for interface
int main()
{
Proc proc(std::make_shared<InterfaceWrap<ThisInterface>>());
proc.GetPtr()->AnyAction();
}
In case anyone is interested, in what follows I provide the edited example code (from the beginning) as it finally works for me.
The solution is basically the answer of Jarod42 (Perhaps this overall approach may not be the most elegant one, as pointed out in the other comments. However, I guess some purposes may justify it).
However, there is one little thing added: casted void pointer arguments. To me this turns out useful when extending the original problem towards, e.g., the member AnyAction having an argument of yet unspecified but "known" type.
... static library ...
// InterfaceWrap.h
//-----------
// dummy include
#include <SomeTClass.h>
struct IAnyAction
{
virtual ~IAnyAction() = default;
virtual void AnyAction(void* arg) = 0;
};
template<typename T>
class InterfaceWrap : public IAnyAction
{
std::shared_ptr<SomeTClass<T>> m_somePtr;
public:
InterfaceWrap();
void AnyAction(void* arg);
};
template<typename T>
InterfaceWrap<T>::InterfaceWrap(){
m_somePtr = std::make_shared<SomeTClass<T>>();
}
template<typename T>
void InterfaceWrap<T>::AnyAction(void* arg) override {
auto thisArg = static_cast<T::Type1*>(arg);
m_somePtr->SomeAction(*thisArg);
}
... *.dll ...
// Proc.h
//-----------
#include <InterfaceWrap.h>
class DLL Proc
{
std::shared_ptr<IAnyAction> m_interfaceWrapPtr;
public:
Proc(std::shared_ptr<IAnyAction> interfaceWrapPtr);
~Proc();
IAnyAction* GetPtr();
};
// Proc.cpp
//-----------
Proc::Proc(std::shared_ptr<IAnyAction> interfaceWrapPtr) : m_interfaceWrapPtr(interfaceWrapPtr) {
}
IAnyAction* Proc::GetPtr() {
return m_interfaceWrapPtr.get();
}
... the application ...
// main.cpp
//-----------
#include <Proc.h>
// dummy includes
#include <ThisType01.h>
#include <ThisType02.h>
#include <ThisType11.h>
#include <ThisType12.h>
class ThisInterfaceA {
public:
using Type1 = ThisType01;
using Type2 = ThisType02;
};
class ThisInterfaceB { // not needed here but perhaps illustrative
public:
using Type1 = ThisType11;
using Type2 = ThisType12;
};
using ThisInterface = ThisInterfaceA;
int main(int argc, char * argv[])
{
Proc proc(std::make_shared<InterfaceWrap<ThisInterface>>());
auto type1 = std::make_shared<ThisInterface::Type1*>();
proc.GetPtr()->AnyAction(type1.get());
return 0;
}
I imitated the std::enable_shared_from_this to create a template class, but I made the class use the type definition in its subclass.
Unfortunately!
Although I used typename, after compiling,
//
// https://ideone.com/eYCBHW http://ideone.com/eYCBHW
#include <iostream>
#include <set>
#include <map>
using namespace std;
template<class _S> struct A {
};
template<class _Subclass>
class Global {
public:
typedef typename _Subclass::connection_t connection_t;
//std::map<std::string, _Subclass::connection_t> connections;
//std::set<_Subclass::connection_t> connections;
//using typename _Subclass::connection_t;
//typename _Subclass::connection_t* connections;
//connection_t* connections;
};
class CConnection {};
class SConnection;
class Client : public Global<Client> {
public:
typedef CConnection connection_t;
};
#if 0
class Server : public Global<Server> {
public:
typedef SConnection connection_t;
};
#endif
class SConnection {};
int main() {
// your code goes here
return 0;
}
GCC complained:
prog.cpp: In instantiation of ‘class Global<Client>’:
prog.cpp:25:23: required from here
prog.cpp:14:43: error: invalid use of incomplete type ‘class Client’
typedef typename _Subclass::connection_t connection_t;
^~~~~~~~~~~~
prog.cpp:25:7: note: forward declaration of ‘class Client’
class Client : public Global<Client> {
^~~~~~
How to solve it?
References
Where and why do I have to put the “template” and “typename” keywords?
C++ - meaning of a statement combining typedef and typename [duplicate]
Two template classes use each other as template argument
Having a typedef at class level requires the template arguments to be complete types. How would the compiler otherwise be able to check, if the type provided as argument actually has some equivalent typedef itself?
Analogously, the following is going to fail:
class C;
using G = Global<C>; // C is not a complete type!
class C // too late...
{
// ...
};
Problem with curiously recurring template pattern, which is what you're trying to implement, that at the point you try to derive, the class is not yet complete, just as in my example above:
class Client : public Global<Client> // client is not yet complete!
{
}; // only HERE, it will get complete, but that's too late for above
Ever wondered, though, why member variables are known within member functions even though being declared after the function? That's because
class C
{
void f() { n = 12; }
int n = 10;
};
is compiled as if it was written as:
class C
{
inline void f();
int n = 10;
};
void C::f() { n = 12; } // n is known now!
This is at the same time the clue where you can use the template argument the way you intend:
template<class T> // different name used! *)
class Global
{
public:
void f()
{
typedef typename T::connection_t connection_t; // possible here!
// (similar to why you can use the static cast as in the link provided)
}
};
That won't help, though, with your members:
std::map<std::string, typename T::connection_t> connections;
// ^ additionally was missing, but won't help either
T still remains incomplete at this point.
Within the comments, though, you only seem to use the connection type. If you don't need the client or server class for any reason other than the typedef, you can solve the issue pretty simply:
template<class T> // different name used! *)
class Global
{
std::map<std::string, T> connections;
// ^ use T directly
};
class Client : public Global<CConnection>
// ^ make sure it is defined BEFORE
{
// ...
};
Otherwise, you need to fall back to other means, e. g. the pimpl pattern, where you would let the implementation class inherit from the template.
*) Identifiers starting with underscore followed by captial letter, as well as those containing two subsequent identifiers, are reserved for the implementation (i. e. for use by the compiler). Defining your own such ones yields undefined behaviour.
Edit (stolen from the comments):
If you need client or server from within Global, you could provide both as separate template paramters as well:
template <typename Base, typename Connection>
{
// use Connection directly, e. g. for member definitions
// and Base within member functions as mandated by CRTP
};
class Client : public Global<Client, CConnection>
{ /* ... */ };
I created a class and I want to force anyone who's trying to construct an object, to use unique_ptr. To do that I thought of declaring the constructor protected and use a friend function that returns a unique_ptr. So here's an example of what I want to do:
template <typename T>
class A
{
public:
friend std::unique_ptr<A<T>> CreateA<T>(int myarg);
protected:
A(int myarg) {}
};
template <typename T>
std::unique_ptr<A<T>> CreateA(int myarg)
{
// Since I declared CreateA as a friend I thought I
// would be able to do that
return std::make_unique<A<T>>(myarg);
}
I did some reading on friend functions and I understood that a friend function provides access to private/protected members of an object of a class.
Is there anyway I can make my example work?
Even without friend functions, my goal is to make the CreateA the only way for someone to create an object.
EDIT
I change the code a bit. I didn't mention that my class takes one template parameter. That makes things more complex apparently.
You can do it this way :-
#include <iostream>
#include <memory>
using namespace std;
class A
{
int arg;
public:
friend unique_ptr<A> CreateA(int myarg);
void showarg() { cout<<arg; }
protected:
A(int myarg): arg(myarg) {}
};
unique_ptr<A> CreateA (int myarg)
{
return std::unique_ptr<A>(new A(myarg));
}
int main()
{
int x=5;
unique_ptr<A> u = CreateA(x);
u->showarg();
return 0;
}
Output :-
5
If you don't want to use friend function you can make the function static & call it like this :-
unique_ptr<A> u = A::CreateA(x);
EDIT :-
In reply to your edit I rewrote the program & it goes like this :-
#include <iostream>
#include <memory>
using namespace std;
template <typename T>
class A
{
T arg;
public:
static std::unique_ptr<A> CreateA(T myarg)
{
return std::unique_ptr<A>( new A(myarg) );
}
void showarg()
{
cout<<arg;
}
protected:
A(T myarg): arg(myarg) {}
};
int main()
{
int x=5;
auto u = A<int>::CreateA(x);
u->showarg();
return 0;
}
Simple & easy !!! But remember you cannot instantiate the object of A. Good Luck !!!
The other answers suggest using a static template function, which I agree is the best solution, because it is simpler.
My answer explains why your friend approach didn't work and how to use the friend approach correctly.
There are two problems in your original code. One is that make_unique is not actually a friend of A, so the call make_unique<A<T>>(myarg); does not have access to A's protected constructor. To avoid this , you can use unique_ptr<A<T>>(new A(myarg)) instead. Theoretically it would be possible to declare make_unique a friend but I'm not even sure of the right syntax for that.
The other issue is the template friends problem. Inside a class template, friend <function-declaration> actually declares a non-template friend.
The C++ FAQ suggests two possible workarounds. One of them is to define the friend function inline. However, in that case the function can only be found by argument-dependent lookup. But since the function does not take A<T> (or A<T> &) as argument, it can never be found this way. So this option is not viable to your situation -- it's more suited to operator overloading.
So the only fix is to declare (and optionally define) the template function before the class definition:
#include <memory>
template<typename T>
class A;
template <typename T>
std::unique_ptr<A<T>> CreateA(int myarg)
{
return std::unique_ptr<A<T>>{new A<T>(myarg)};
}
template <typename T>
class A
{
friend std::unique_ptr<A<T>> CreateA <> (int myarg);
// refers to existing template ^^
protected:
A(int myarg) {}
};
int main()
{
auto x = CreateA<int>(5);
}
Note: It is possible to declare CreateA where I have defined it, and put the function definition later. However, the code I have posted works -- despite A not being defined when new A<T>(myarg) appears in the source -- because CreateA is not instantiated until it is called, at which point A will be defined.
Create a static function that instantiates the protected constructor.
#include<iostream>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include <memory>
using namespace std;
template< typename T >
class A
{
public:
static void CreateA(int myarg, std::unique_ptr<A<T>>& objA, T t) {
std::unique_ptr<A<T>> objB(new A(myarg, t));
objA = std::move(objB);
}
protected:
A(int myarg, T t) {
m_t = t;
}
private:
T m_t;
};
int main() {
int myArg = 0;
std::unique_ptr<A<int>> anotherObjA;
A<int>::CreateA(myArg, anotherObjA, myArg);
return 0;
}
When writing a framework I got following problem:
I have class A and class B wchich is derived from class A.
class A has a function wchich returns B*.
Of course, it's not difficult:
#include <iostream>
using namespace std;
class B; // forward declaration
class A
{
public:
B* ReturnSomeData();
};
class B : public A
{
};
// Implementation:
B* A::ReturnSomeData()
{
return new B; // doesn't matter how the function makes pointer
}
int main()
{
A sth;
cout << sth.ReturnSomeData(); // print adress
}
However I had to use templates like here:
#include <iostream>
using namespace std;
// This "forward declaration":
template <class Number>
class B<Number>;
// cannot be compiled:
// "7 error: 'B' is not a template"
template <class Number>
class A
{
public:
B<Number>* ReturnSomeData();
};
template <class Number>
class B : public A<Number>
{
};
// Implementation:
template <class Number>
B<Number>* A<Number>::ReturnSomeData()
{
return new B<Number>;
}
int main()
{
A<int> sth;
cout << sth.ReturnSomeData();
}
Look at the code. As you can see I don't know how to deal with unknown by A B*. Is it possible to write forward declaration? Or I need something different?
Yes, I searched and I see there are many posts about template declarations but can't find solve for my individual problem. It's a bit complex for me.
Thanks for help.
Your forward declaration is incorrect. It needs to be:
template <class Number>
class B;
^ no argument list
Two-phase lookup question:
Is there a more synthetic way to write this code, i.e. avoiding all those using directives?
Something like using CBase<T>; is what I would like, but it is not accepted.
#include <iostream>
template <typename T>
class CBase
{
protected:
int a, b, c, d; // many more...
public:
CBase() {
a = 123; c = 0;
}
};
template <typename T>
class CDer : public CBase<T>
{
// using CBase<T>; // error, but this is what I would like
using CBase<T>::a;
using CBase<T>::b;
//...
public:
CDer() {
std::cout << a << this->c;
}
};
int main()
{
CDer<int> cd;
}
In my real code there are many more member variables/functions, and I was wondering if it is possible to write shorter code in some way.
Of course, using the this->c syntax does not solve the problem...
Thank's!
gcc 4.1
MacOS X 10.6
I reduced the testcase and then consider three options
template<typename T> struct Base { int a; };
Option 1
template<typename T> struct Der : Base<T> {
void f() {
int &ra = Der::a;
// now use ra
}
}
Option 2
template<typename T> struct Der : Base<T> {
void f() {
// use this->a instead
// or Der::a
}
}
Option 3
// use your using declarations
It doesn't look like most of those variables are parameterized. Does CBase use them all, or just a? If not, move them into a new non-template base of CDer.
Or, pack them all into a POD struct and then using CBase<T>::m_ints;.
High overhead solution: non-templated virtual base.
Not sure but worth a try: nest the definition of CDer inside CBase and then typedef it into namespace scope.