! i'm working on a gun template,it should be like this:
template <Bullet>
class gun
{
};
that Bullet is a class that will define in other file,my question is how i can use this bullet in gun as a type? how can i use a class as a template in other class? i want a little bit long explanation!
thanks...!
this is what i tried to do:
#include "Bullet.h"
#include <iostream>
using namespace std;
#define BulletWeapon1 100
#define BulletWeapon2 30
#define BulletWeapon3 50
enum Weapons
{
Gun1,Gun2,Gun3
}CurrentWeapon;
template <class T=Bullet>
class Gun
{
};
int main()
{
return 0;
}
If you need only need the Bullet class inside gun, then you can just don't use a template:
class gun {
Bullet x;
// ...
};
otherwise, if you want to allow any class but provide a default class Bullet, you can use:
template <class T = Bullet>
class gun {
T x;
// ...
};
In particular, if you want to make sure that T is always a base class of Bullet, you can play around with type traits such as std::enable_if and std::is_base_of.
On a side note, please try to avoid statements like using namespace std; and begin getting used to the std:: prefix instead. It will save you some headaches when you'll have problems of multiple definitions or weird look ups.
Also, try to avoid #defines as well. This:
#define BulletWeapon1 100
#define BulletWeapon2 30
#define BulletWeapon3 50
can be converted to:
const int BulletWeapon1 = 100;
const int BulletWeapon2 = 30;
const int BulletWeapon3 = 50;
Finally notice that in C++11 you can use enum classes which are a little bit more type safe than simple enums:
enum Weapons { Gun1,Gun2,Gun3 } CurrentWeapon;
can become:
enum class Weapons { Gun1, Gun2, Gun3 } CurrentWeapon = Weapons::Gun1;
Related
I am trying to find a way to group the main types and constants used by my project into a namespace, and then I'd like to import them in all my classes with "using namespace". I can't figure out why this piece of code doesn't compile, g++ error says:
expected nested-name-specifier before 'namespace'
What options do I have to have all my types and constants grouped together? I tried making Traits a struct and then using inheritance but this gives problems with templates, another way is writing in all classes something like:
using scalar_t = Traits::scalar_t;
Thanks for any tip.
#include <iostream>
namespace Traits {
constexpr int N = 3;
using scalar_t = double;
};
struct Entity {
using namespace Traits; // problems here
scalar_t foo() const;
int n = N;
};
scalar_t Entity::foo() const { return N; } // problems here
int main()
{
Entity e;
e.foo();
return 0;
}
The language doesn't actually allow you to import a namespace at class scope. You can solve this by adding another level of indirection, viz. wrapping your class in a namespace, where you can of course import other namespaces.
namespace Indirection
{
using namespace Traits; // ok at namespace scope
// now everything from Traits is avaliable
struct Entity
{
scalar_t foo() const; // scalar_t is visible, yay!
int n = N;
};
scalar_t Entity::foo() const { return N; } // also ok, since in same namespace
}
Of course, you don't want to ever have to mention the Indirection namespace again, so you can just lift the Entity out of that namespace.
using Indirection::Entity;
and now it's as if Indirection never existed at all.
Here's a demo.
I have a namespace, N0, that has sub-namespaces including N1. The calling code only knows about the outer namespace. I'd like to write a function in the outer namespace that returns a std::unique_ptr<N1::T> where that result is consumed elsewhere in N0. However, the caller shouldn't know about N1. What I'd like to do is something like:
// N0.h
namespace N0 {
typename T; // This isn't real C++.
std::unique_ptr<T> foo();
void bar(std::unique_ptr<T>&&);
}
// N0.cpp
#include "N1.h" // Get N1::T
namespace N0 {
typedef N1::T T;
...
}
That is, I'd like to expose a type that the caller can't see but internally I'd like to actually use a type in a different namespace. This way elsewhere someone could just forward-declare namespace N0 { class T; } without having to know that T is actually in N1.
I could move T itself into N0, but it really belongs in N1.
I could wrap T with a dummy class in N0, but that's ugly, and the pointer should basically do that.
I could probably make a class N0::T that subclasses N1::T, but that seems icky too.
Is there no way for N0 to forward declare that "I have a type and you don't need to know what it is" and have that type actually be in a different namespace? Put another way: Why is class C; class C{}; legal but class C; typedef int C; is illegal? (Likewise class C; using C = int; or typedef C; typedef int C;.) They seem fundamentally the same to me and I can't think of a clever template trick to get around it. The only difference I can think of is that the typedef version wouldn't be subject to Koenig lookup.
I mean you could do this:
// N0.h
namespace N0 {
std::unique_ptr<T> foo();
void bar(std::unique_ptr<T>&&);
}
// N0.cpp
namespace N0 {
typedef N1::T t;
}
#include "N0.h"
namespace N0 {
// whatever...
}
In the situation you have described, the foo should be implemented as a template function:
namespace N0 {
template <typename T>
std::unique_ptr<T> foo(){...};
template <typename T>
void bar(std::unique_ptr<T>&&){...};
}
And you should using a wrap/overload function to do the final trick:
namespace N0 {
std::unique_ptr<N1::T> foo() { return foo<N1::T>(); }
//for bar there is no need to wrap, cause the T could be resolved by parameters.
}
Here's the best I've come up with, which seems to work. I still feel like there should be a way to not use "tricks" to make N1::T fully hidden from callers:
// N0.h
#pragma once
#include <memory>
namespace N0 {
struct OpaqueObject { virtual ~OpaqueObject() {} };
std::unique_ptr<OpaqueObject> foo();
void bar(std::unique_ptr<OpaqueObject>&&);
}
//N0.cpp
#include "N1.h"
namespace N0 {
std::unique_ptr<OpaqueObject> foo() { return std::unique_ptr<N1::T>(new N1::T()); }
void bar(std::unique_ptr<OpaqueObject> &&) {}
}
// N1.h
#pragma once
#include "N0.h"
namespace N1 {
class T : public N0::OpaqueObject {};
}
// test.cpp
#include "N0.h"
int main() {
auto x = N0::foo();
N0::bar(std::move(x));
}
I have many types of game-object that are related together is some ways.
All relations is implemented by Map<K1,K2>.
#include <vector>
using namespace std;
template<class K1,class K2> class Map{ //N:N relation
public: std::vector<K2*> getK2(K1* k1){/* some code */return std::vector<K2*>();}
public: std::vector<K1*> getK1(K2* k2){/* some code */return std::vector<K1*>();}
//... various function ...
};
Here is the hub class GameRelation that facilitates all relation query :-
(just an example, no need to pay attention to all detail)
class Human{}; class House{}; class Dog{};
class GameRelation{
public:
#define RELATION(A,B,EnumName) Map<A,B> Map##EnumName; \
enum EnumName##Enum{EnumName}; \
std::vector<B*> getAllRight(EnumName##Enum e,A* a){ \
return Map##EnumName.getK2(a); \
}
//... various function ...
RELATION(Human,House,Own)
//I can insert any relation that I want
};
The above macro expands into something like :-
Map<Human,House> MapOwn;
enum OwnEnum{Own};
std::vector<House*> getAllRight(OwnEnum e,Human* a){
return MapOwn.getK2(a);
}
Here is how it can be used (full demo):-
int main() {
GameRelation gameRelation;
std::vector<House*> houses=gameRelation.getAllRight(GameRelation::Own,new Human());
//get all "House" that is "Own" by a "Human"
return 0;
}
After some testing, it works good. Everyone is happy with the magical result.
However, my conscious tell me that it is a hack.
It is also a little bad for content-assist (e.g. intellisense) and automatic refactoring.
I also need the awesome hacking X-MACRO if I want to move their implementation to .cpp.
Question:
Is there any elegant (less hack) way? What is it?
"No" can be a valid answer.
Is X-MACRO the (professional) way to go when I need such (strange) feature?
struct GameRelation{
template <typename A, typename B>
struct Relation {
std::vector<B*> getAllRight(A* a) {
return map.getK2(a);
}
private:
Map<A, B> map;
};
Relation<Human, House> own;
};
int main() {
GameRelation gameRelation;
std::vector<House*> houses = gameRelation.own.getAllRight(new Human());
}
I am currently learning C++ and trying to understand the usage of structs.
in C++. As far as I'm aware, if you want to define a function after the main() function, you have to declare it beforehand, like in this function (Please tell me if I'm wrong with it):
#include "stdafx.h"
#include <iostream>
#include <string>
void printText(std::string); // <-- DECLARATION
int main()
{
std::string text = "This text gets printed.";
printText(text);
}
void printText(std::string text)
{
std::cout << text << std::endl;
}
My question now is if there is a way to do the same with structs. I don't want having to always define a struct before the main() function, just because I prefer it like that. However, I get an error when I try doing it like that:
//THIS program DOESN'T work.
#include "stdafx.h"
#include <iostream>
#include <string>
struct Products {std::string}; // <-- MY declaration which DOESN'T work
int main()
{
Products products;
products.product = "Apple";
std::cout << products.product << std::endl;
}
struct Products
{
std::string product;
};
When I delete the decleration and instead define the struct before the main function, the program works so I assume I'm somehow wrong with the decleration:
//THIS program DOES work
#include "stdafx.h"
#include <iostream>
#include <string>
struct Products
{
std::string product;
};
int main()
{
Products products;
products.product = "Apple";
std::cout << products.product << std::endl;
}
Could someone tell me if there is some way to declare a struct like that? Bear with me if I have any major mistake in the code, I'm just a beginner.
Thanks in advance!
You can pre-declare (forward-declare) a class type in C++.
struct Products;
However, a class type declared in this way is incomplete. Incomplete types can only be used in a number of very limited ways. You will be able to declare pointers or references to such type, you will be able to mention it in non-defining function declarations etc., but you will not be able to define objects of such incomplete type or access their members.
If you want to define objects of class Products or access members of class Products, you have no other choice but to fully define the class before such use.
In your case you are defining an object of type Products in main as well as accessing members of class Products there. This means that you have to completely define Products before main.
In your particular case a forward declaration wont help, because a forward declaration only allows you to use pointers or references, as e.g. in
struct foo;
foo* bar(foo f*) { return f;}
struct foo { int x; }
However,
struct Products {std::string};
is not a declaration, but if you want an ill-formed declaration and definition.
The correct forward declaration would be:
struct Products;
I have a class like this:
class TType {
public:
...
enum binary_type {
bt_a = 0,
bt_xyz,
....
bt_ak = 10,
....
};
}
and I use it in several places, also the enum:
if(var12 == TType::bt_a ) { ....
Now I imported a C library which has exactly the same enum (same keys, same values, same size) inside one of it's headerfiles:
typedef enum data_types_e {
bt_a = 0,
bt_xyz,
....
} data_types;
How can I define the enum in the c++ class definition to use the declaration of the c headerfile?
I want to continue using the enum the same way as before (TType::bt_a), and avoid copying the whole enum. Furthermore I don't wont to modify the library (otherwise a preprocessor-macro would do the trick) and I want changes made in the library also be made to the enum in my class.
Neither a typedef inside the c++ class definition nor a type alias (c++11) seem to work in this situation.
"How can I define the enum in the c++ class definition to use the declaration of the c headerfile?"
You can simply reuse the values from the c-style enum:
#include "TheOtherEnum.h"
...
enum binary_type {
bt_a = ::bt_a,
bt_xyz = ::bt_xyz,
....
bt_ak = ::bt_ak,
....
};
"Neither a typedef inside the c++ class definition nor a type alias (c++11) seem to work in this situation."
Yes these would work to provide the correct enum type, but you'll still need to qualify the values from the global namespace and not for nested to your class.
You can make C++ enum dependant of C enum:
typedef enum data_types_e {
bt_a = 0,
bt_xyz,
....
} data_types;
// ...
class TType {
public:
...
enum binary_type {
bt_a = bt_a,
bt_xyz = bt_xyz,
....
};
}
If possible, try renaming your class TType say, class TType_1.
//=============CLibraryFileContainingEnum.h=================
typedef enum data_types_e
{
bt_a = 9999,
bt_xyz
} data_types;
//==========================================================
//==========================================================
class TType_1
{
public:
enum binary_type
{
bt_a = 8878,
bt_xyz
};
};
namespace TType
{
#include "CLibraryFileContainingEnum.h"
}
int main()
{
int a = TType::bt_a; //this prints 9999
cout << a << endl;
return 0;
}
//==========================================================
Here is my answer, this is an old topic, but better lately than never
class TType {
public :
public:
...
#undef __cplusplus
#include "yourheaderc.h"
#define __cplusplus
}
maybe with a typedef binary_type data_types to preserve your nominations
But this solution is available if your header don't contains syntax C forbidden in C++. I'm currently searching a new solution because there are prototypes in my header that contains something like :
void afunction( unsigned long id,
enum T_TYPE type,
enum T_CHAR characteristic,
unsigned short number,
unsigned short value);
because T_TYPE and T_CHAR are not typedef-ed but this syntax is non-sense in C++ because it's the declaration syntax. So my solution is not appropriate if you are in a similar case.