I need only my mesh class to be able to create these classes, and i would like to not make these classes nested, because of too long qualified name if so. How can i do it best?
struct Handle
{
explicit Handle(int i) : _index(i) {}
bool IsValid() { return _index != NO_HANDLE; }
protected:
enum { NO_HANDLE = -1 };
int _index;
};
// **************************************************************************************
struct HalfEdgeHandle : Handle
{
HalfEdgeHandle(int i) : Handle(i) {}
static HalfEdgeHandle GetInvalid() { return HalfEdgeHandle(NO_HANDLE); }
};
// **************************************************************************************
struct FaceHandle : Handle
{
FaceHandle(int i) : Handle(i) {}
static FaceHandle GetInvalid() { return FaceHandle(NO_HANDLE); }
};
// **************************************************************************************
struct VertexHandle : Handle
{
VertexHandle(int i) : Handle(i) {}
static VertexHandle GetInvalid() { return VertexHandle(NO_HANDLE); }
};
Only invalid handle should be accessible outside, for now i think it can be done by using static variables.
Use friend.
class Factory;
struct Handle
{
protected:
explicit Handle(int i) : _index(i) {}
public:
bool IsValid() { return _index != NO_HANDLE; }
protected:
enum { NO_HANDLE = -1 };
int _index;
friend class Factory; // and so on in Derived classes
};
Related
If I have a class called Node, would it be bad, if objects of the Node class knew their NodeType, and the NodeType would be used to cast to a specific interface like this:
// NodeType
enum class NodeType : uint8_t
{
None = 0,
Foo = 1 << 0,
Bar = 1 << 1,
FooBar = 1 << 2,
FooMask = Foo | FooBar,
BarMask = Bar | FooBar,
};
inline constexpr uint8_t operator&(const NodeType& t_lhs, const NodeType& t_rhs)
{
return static_cast<uint8_t>(t_lhs) & static_cast<uint8_t>(t_rhs);
}
// Base Node Class
class Node
{
public:
virtual NodeType GetNodeType() const = 0;
};
// Interfaces
class IFoo
{
public:
virtual ~IFoo() = default;
virtual void FooSpecificMethod() const = 0;
};
class IBar
{
public:
virtual ~IBar() = default;
virtual void BarSpecificMethod() const = 0;
};
// Derived Node Classes
class FooNode : public Node, public IFoo
{
public:
NodeType GetNodeType() const override { return NodeType::Foo; }
void FooSpecificMethod() const override { std::cout << "Foo.\n"; }
};
class BarNode : public Node, public IBar
{
public:
NodeType GetNodeType() const override { return NodeType::Bar; }
void BarSpecificMethod() const override { std::cout << "Bar.\n"; }
};
class FooBarNode : public Node, public IFoo, public IBar
{
public:
NodeType GetNodeType() const override { return NodeType::FooBar; }
void FooSpecificMethod() const override { std::cout << "Foo.\n"; }
void BarSpecificMethod() const override { std::cout << "Bar.\n"; }
};
// Use of NodeType and Interfaces
std::vector<std::unique_ptr<Node>> GetNodes()
{
std::vector<std::unique_ptr<Node>> nodes{};
nodes.push_back(std::make_unique<FooNode>());
nodes.push_back(std::make_unique<FooNode>());
nodes.push_back(std::make_unique<BarNode>());
nodes.push_back(std::make_unique<FooBarNode>());
nodes.push_back(std::make_unique<FooBarNode>());
nodes.push_back(std::make_unique<FooBarNode>());
return nodes;
}
int main()
{
std::vector<std::unique_ptr<Node>> nodes{ GetNodes() };
for (const auto& node : nodes)
{
if ((node->GetNodeType() & NodeType::FooMask) != 0)
dynamic_cast<const IFoo*>(node.get())->FooSpecificMethod();
}
for (const auto& node : nodes)
{
if ((node->GetNodeType() & NodeType::BarMask) != 0)
dynamic_cast<const IBar*>(node.get())->BarSpecificMethod();
}
}
My goal is to do type specific things on objects in a polymorphic collection like in the last code snippet. Is this a bad approach? Is there any more OO approach to this?
Is this a bad approach? Is there any more OO approach to this?
Yes. You can just dynamic_cast to the appropriate pointer type and check the result is not null.
int main()
{
std::vector<std::unique_ptr<Node>> nodes{ GetNodes() };
for (const auto& node : nodes)
{
if (auto foo = dynamic_cast<const IFoo*>(node.get()))
foo->FooSpecificMethod();
}
for (const auto& node : nodes)
{
if (auto bar = dynamic_cast<const IBar*>(node.get()))
bar->BarSpecificMethod();
}
}
If for some reason you want to avoid dynamic_cast, you can add virtual functions to Node. This is perhaps the "most OO" way.
class Node
{
public:
virtual ~Node() = default;
virtual const IFoo * asFoo() const { return nullptr; }
virtual const IBar * asBar() const { return nullptr; }
};
class FooNode : public Node, public IFoo
{
public:
const IFoo* asFoo() const override { return this; }
void FooSpecificMethod() const override { std::cout << "Foo.\n"; }
};
class BarNode : public Node, public IBar
{
public:
const IBar* asBar() const override { return this; }
void BarSpecificMethod() const override { std::cout << "Bar.\n"; }
};
class FooBarNode : public Node, public IFoo, public IBar
{
public:
const IFoo* asFoo() const override { return this; }
const IBar* asBar() const override { return this; }
void FooSpecificMethod() const override { std::cout << "Foo.\n"; }
void BarSpecificMethod() const override { std::cout << "Bar.\n"; }
};
int main()
{
std::vector<std::unique_ptr<Node>> nodes{ GetNodes() };
for (const auto& node : nodes)
{
if (auto foo = node->asFoo())
foo->FooSpecificMethod();
}
for (const auto& node : nodes)
{
if (auto bar = node->asBar())
bar->BarSpecificMethod();
}
}
Here is a simplified example (from gMock Cookbook) of a class template that I want to mock:
class StackInterface {
public:
virtual ~StackInterface();
virtual int GetSize() const {
return 3;
}
};
template<typename Elem>
class MockStack : public StackInterface<Elem> {
public:
MockStack() : StackInterface<Elem>(){};
MOCK_METHOD(int, GetSize, (), (const, override));
};
I'm using it as follows:
class StackTest : public testing::Test {
public:
StackTest() {
mockStack_ = std::make_shared<MockStack<int>>();
}
protected:
std::shared_ptr<MockStack<int>> mockStack_;
};
TEST_F(StackTest, TestGetSize1) {
EXPECT_CALL(*mockStack_, GetSize()).WillRepeatedly(testing::Invoke([&]() -> int { return 5; }));
StackInterface<int> myStack;
auto res = myStack.GetSize();
EXPECT_EQ(res, 5);
}
This test fails because returned value is 3 which is my real function - Why is my mock implementation being ignored? How can I ensure the mock implementation is used?
The GetSize method needs to be called by the mock object. That's mockStack_
template <typename Elem>
class StackInterface {
public:
StackInterface() {}
virtual ~StackInterface() {}
virtual int GetSize() const {
return 3;
}
};
template <typename Elem>
class MockStack : public StackInterface<Elem> {
public:
MockStack() : StackInterface<Elem>() {
ON_CALL(*this, GetSize()).WillByDefault(Return(1)); }
~MockStack() {}
MOCK_METHOD(int, GetSize, (), (const, override));
};
class StackTest : public testing::Test {
public:
StackTest() {
mockStack_ = std::make_shared<MockStack<int>>();
}
protected:
std::shared_ptr<MockStack<int>> mockStack_;
};
TEST_F(StackTest, TestGetSize1) {
EXPECT_CALL(*mockStack_, GetSize()).WillRepeatedly(testing::Invoke([&]() -> int { return 5; }));
EXPECT_EQ(mockStack_->GetSize(), 5);
}
as the code below made for example purposes in C #, I would have had to do in C ++, if so how do you do?
public class MyClassTest{
public int testint1{get;set;}
public MyClassTest2 classTest2{get;set;}
}
public class MyClassTest2{
public int testint2{get;set;}
public MyClassTest classTest{get;set;}
}
Something like this.
class MyClassTest {
private: // optional: C++ classes are private by default
int testint1;
public:
int getTestInt1() const { return testint1; }
void setTestInt1(int t) { testint1 = t; }
};
Or you could make your member name distinct and skip the get/set keywords:
class MyClassTest {
private:
int testint1_;
public:
int testint1() const { return testint1_; }
void testint1(int t) { testint1_ = t; }
};
There is no equivalent to this in the current C++ standard, you just have to create getter/setter methods for any fields you want:
class MyClass {
public:
MyClass() {}
// note const specifier indicates method guarantees
// no changes to class instance and noexcept specifier
// tells compiler that this method is no-throw guaranteed
int get_x() const noexcept { return x; }
void set_x(int _x) { x = _x; }
private:
int x;
};
In Visual Studio (mine is 2013), it could be done in this way:
__declspec(property(get = Get, put = Set)) bool Switch;
bool Get() { return m_bSwitch; }
void Set(bool val) { m_bSwitch = val; }
bool m_bSwitch;
in a Class.
I have one problem on conversion of one class to base.
This is the code :
#define Derive_NTag_CRTP(Type) class Type: public NTagBase<Type>
template<typename Derived>
class NTagBase{
public:
NTagBase(var name) { this->_name = name; }
NTagBase(const NTagBase & ntag) { this->_name = ntag._name; }
NTagBase* append(NTagBase<Derived> *item) { _children.push_back(item); return this; }
private:
var _name;
vector<NTagBase *> _children;
};
Derive_NTag_CRTP(NTag){
public:
NTag(var name) : NTagBase(name) { }
NTag(const NTagBase & ntag) : NTagBase(ntag) { }
};
Derive_NTag_CRTP(NTagInput){
public:
NTagInput(var type) : NTagBase("input") { _type = type; }
NTagInput(const NTagBase & ntag) : NTagBase(ntag) { }
private:
var _type;
};
int main(int argc, char **argv, char **envv)
{
NTag div("div");
NTagInput button("button");
div.append(new NTag("span"));
div.append(&button);// Error 1 error C2664: 'NTagBase<Derived>::append': can not convert parameter 1 from 'NTagInput *' to 'NTagBase<Derived> *'
}
How can I fix that without do one explicit cast?
PS: I need to have one vector of pointers of base class and append into that all kind of classes inherited.
div is NTag, i.e. NTagBase<NTag>. button is NTagInput, i.e. NTagBase<NTagInput>, while div's append() expects a NTagBase<NTag> which is unrelated. You should change append to something like
template <typename D>
NTagBase* append(NTagBase<D> item) { ... }
However, you still cannot store items of different types in a single vector. Better make a non-template e.g. Base of NTagBase and let your vector contain pointers (or std::unique_ptr) to Base.
div.append (...) clearly need to be overloaded because after inherited from the base, it wouldn't understand the second signature ie div.append(&button); or you can create a wrapper class that pack every object type to it own define and provide a mechanism for reversing back to the original type.
Alternatively , just overload any necessary function .
class NTagInput;
class AppendInputRegister;
template<typename Derived>
class NTagBase{
public:
NTagBase(string name) { this->_name = name; }
NTagBase(const NTagBase & ntag) { this->_name = ntag._name; }
NTagBase* append(NTagBase<Derived> *item) {
_children.push_back((NTagBase *)item);
return this;
}
private:
string _name;
vector<NTagBase *> _children;
};
class NTag: public NTagBase<NTag>{
public:
NTag(string name) : NTagBase(name) { }
NTag(const NTagBase & ntag) : NTagBase(ntag) { }
NTagBase* append(NTagBase<NTagInput> *item) {
append((NTagBase<NTag> *)item);
}
NTagBase* append(NTagBase<NTag> *item) {
NTagBase::append((NTagBase<NTag> *)item);
}
};
class NTagInput: public NTagBase<NTagInput>{
public:
NTagInput(string type) : NTagBase("input") { _type = type; }
NTagInput(const NTagBase & ntag) : NTagBase(ntag) { }
private:
string _type;
};
I have the following class:
class ValueSetter: public IValueSetter
{
public:
explicit ValueSetter(CContainer* container)
: _container(container)
{
}
virtual void operator()(const int value, const int index) const
{
_container->values[index].value.i = value;
}
virtual void operator()(const double value, const int index) const
{
_container->values[index].value.d = value;
}
virtual void operator()(const std::string& value, const int index) const
{
...
_container->values[index].value.s = _strdup(value.c_str());
}
private:
CContainer* _container;
};
This class operates on CContainer which stores its data in a buffer of unions. I pass ValueSetter to a Container class which has no knowledge of CContainer. Indeed, in the future I'm hoping that CContainer (which I received via a C API) will disappear and that the values are instead organised in a std::vector or std::list. My Container's interface shouldn't need to change because of this and shouldn't care about how the data is stored in memory.
With this in mind, I'd prefer instead something roughly along these lines:
class IntValueSetter: public IIntValueSetter
{
public:
explicit IntValueSetter(Container* container)
: _container(container)
{
}
virtual void operator()(const int value, const int index) const
{
_container->values[index].value.i = value;
}
private:
CContainer_3* _container;
}
or:
class IntValueSetter: public IIntValueSetter
{
public:
explicit IntValueSetter(std::vector<int> values)
: _values(values)
{
}
...
}
but I'd need to be able to use them as follows:
ValueSetter<int> valueSetter;
instead of
IntValueSetter valueSetter;
How can I do this?
Just do the obvious. There's no requirement that a template specialization have anything in common with another specialization or with the original template. So:
class IIntValueSetter {
};
template <class Ty> class ValueSetter; // declared but not defined
template <>
class ValueSetter<int> : public IIntValueSetter {
// whatever
};
ValueSetter<int> vsi;
If I get you right, you just need to write a class template:
template <typename T>
class ValueSetter
{
public:
explicit ValueSetter(std::vector<T> values): _values(values)
{
}
virtual void operator()(const T value, const int index) const
{
_container->values[index].value.i = value;
}
// etc.
};
I guess I'm looking for something like this. I've only implemented for int below, but each type would get its own interface class and implementation class. I'd love to hear your comments on this approach!
template<typename V>
class IValueSetter
{
public:
};
template<>
class IValueSetter<std::string>
{
public:
virtual void operator()(const std::string& value, int index) const = 0;
};
template<typename V>
class ValueSetter
{
};
template<>
class ValueSetter<std::string>: public IValueSetter<std::string>
{
public:
explicit ValueSetter2(CContainer* container)
: _container(container)
{
}
void operator()(const std::string& value, int index) const
{
_container->values[index].value.s = _strdup(value.c_str());
}
private:
CContainer* _container;
};
template<>
class NewValueSetter<std::string>: public IValueSetter<std::string>
{
public:
explicit NewValueSetter(std::shared_ptr<std::list<std::string>> values)
: _values(values)
{
}
void operator()(const std::string& value, int index) const
{
(*values)[index] = value;
}
private:
std::shared_ptr<std::list<std::string>> _values;
};