-
Notifications
You must be signed in to change notification settings - Fork 3
Make ngraph_bridge::Node members const where possible #69
Make ngraph_bridge::Node members const where possible #69
Conversation
Refactor emitter tests according to above const change Make ngraph_bridge::Node constructors protected Use more explicit names for function arguments for readability ngraph_graph.h and .cc clang-format Google
@@ -25,11 +25,11 @@ struct testEmitter : public Emitter { | |||
NgraphNodePtr data1; | |||
NgraphNodePtr data2; | |||
NgraphNodePtr data3; | |||
testEmitter() { | |||
testEmitter(nnvmNodePtr n) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why add the nnvmNodePtr to the test constructor when it isn't used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nevermind, found the usecase with Adam's help.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ran clang-format on ngraph_graph.h and cc files so I annotated with comments to help navigate those diffs.
for (auto i : n->inputs_) { | ||
if (i->name_ == "") i->name_ = randomString(6); | ||
if (n->name_ == "") n->name_ = randomString(6); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ran clang-format on this file and most of the changes are due to clang-format (non-functional). So, adding some comments to draw attention to the functional changes.
@@ -250,7 +240,7 @@ void Graph::CollapseSubgraphs() { | |||
// loop variable for undefined number of subgraphs | |||
int i = 1; | |||
while (true) { | |||
auto tmpGraph = std::make_shared<Graph>(); | |||
auto tmpGraph = std::make_shared<Graph>("subgraph_" + std::to_string(i)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved Graph name creation to Graph construction time to allow const name
@@ -265,7 +255,6 @@ void Graph::CollapseSubgraphs() { | |||
// set node name and shape based on last node in the subgraph | |||
auto name = tmpGraph->nodes_.back()->name_; | |||
auto shape = tmpGraph->nodes_.back()->shape_; | |||
tmpGraph->name_ = "subgraph_" + name + "_" + randomString(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... instead of setting on name inside the loop
@@ -42,17 +43,23 @@ using nnvmNodePtr = std::shared_ptr<nnvm::Node>; | |||
using NodePtr = std::shared_ptr<Node>; | |||
|
|||
// Possible Types of nodes in Current Version | |||
enum class NodeType {kVariable, kAux, kOp, kGraph}; | |||
enum class NodeType { kVariable, kAux, kOp, kGraph }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few changes in this file due to clang-format but mostly these are "real" changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good. Would like to hear your feedback on the comments I provided please.
Node(NodeType t, const nnvmNodePtr n, std::string s, std::vector<NodePtr> i) | ||
: type_(t), orig_node_(n), name_(s), inputs_(i){}; | ||
protected: | ||
Node(NodeType type, nnvmNodePtr node, const std::string& name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of the logic on line 54, couldn't you just give it a default parameter value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can, but if I do I would likely want to have a default parameter for the inputs_ argument as well. This would mean collapsing to a single ctor per class. I have mixed feelings about this. What do other people think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the default value for the inputs in the first constructor is just an empty vector, I think it would be okay to create 1 constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you change the ordering, you would not. Let's not dwell on it though. Having conditional within the initializer lists does slow down construction though.
}; | ||
|
||
// Node for storing operations | ||
class OpNode : public Node { | ||
public: | ||
// Include operation in graphviz | ||
std::string createNodeLabel() { | ||
std::string createNodeLabel() override { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs to be virtual
as well. I could be wrong here, but I will double check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I double-checked. This needs to be virtual
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
virtual and override are mutually exclusive, per my understanding. virtual => the function can be overridden by a child class. override => the function is overriding a virtual function from the parent class. please send your documentation. Here's mine:
http://en.cppreference.com/w/cpp/language/override
Note that B::foo() is not marked virtual.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adstraw kinda.. if I remember correctly override
is complementary to virtual
. It's a hint to a compiler that you actually want to override a virtual method. If you make a mistake and use it on a non-virtual method the compiler will get upset. You don't have to use override
on a virtual method you would like to override but it's considered a good practice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My documentation is in the form of slides and is called Information Hiding. You can find the explanation in Effective C++. I will concede to your documentation for now as it seems to be fine. I like en.cppreference.com.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Krovatkin That is the way I understand it as well. Non-virtual functions are binded statically to objects. Thus I'm not sure if the proper function will be called. A unit test would resolve this debate 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ransford2011 it should do the right thing AFAIK. override
is kinda "superset" of virtual
in a sense it adds virtual
to the declaration to which override
was applied to and it also checks that the method in a base class is indeed virtual
so it can be overridden. I'm used to a combo of virtual/override
I didn't realize the standard also allows me to just use override
.
As usual, C++ takes a neat idea and makes it confusing. In c# if you use override
and virtual
the compiler will complain, so there's just one way in which override
is allowed to be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#include <iostream>
struct A {
virtual void v() { std::cout << "A::v" << std::endl; };
void m() { std::cout << "A::m" << std::endl; };
};
struct B : public A {
virtual void v() override { std::cout << "B::v" << std::endl; };
//void m() override {}; ERROR : overrides non-virtual method
virtual void m() { std::cout << "B::m" << std::endl; }; //probably doesn't do what a user wanted
};
struct C : public A {
void v() override { std::cout << "C::v" << std::endl; };
};
int main() {
A* a = new A();
A* b = new B();
A* c = new C();
a->v(); //A::v
b->v(); //B::v
c->v(); //C::v
a->m(); //A::m
b->m(); //A::m oopsie
return 0;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😆 . Thanks for running that small experiment. As @adstraw has shown from his reference, the behavior is as intended. That's good for me to know as I can save some keystrokes from typing virtual all the time. Thanks again!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ransford you didn't delete a,b,c in your code. Memory leak! Could you please fix that??? :)
Seriously though... Thanks for following up!
hold off on merge. I missed a unit test failure ngraph_graph.graph_init. will take care of that now. |
fixed test issue... can't check for empty string when using default Graph ctor now that the name is randomized. |
Refactor emitter tests according to above const change
Make ngraph_bridge::Node constructors protected
Use more explicit names for function arguments for readability
ngraph_graph.h and .cc clang-format Google