Date
1 - 6 of 6
Review: compaction as we build closures (issue766041)
aco...@...
http://codereview.appspot.com/766041/diff/1/7
File src/liboslexec/bsdf_diffuse.cpp (right): http://codereview.appspot.com/766041/diff/1/7#newcode51 src/liboslexec/bsdf_diffuse.cpp:51: return m_N == comp->m_N && base_mergeable(other); Wouldn't it be better to just call the parent's method rather than defining base_mergeable? http://codereview.appspot.com/766041/show |
|
Larry Gritz <l...@...>
On Mar 25, 2010, at 4:38 PM, <aco...@...> <aco...@...> wrote:
But then if somebody forgets to provide a closure subclass with a mergeable method, it will revert to the parent class, which will be wrong, wrong, wrong, it will say it's mergeable without being aware of any subclass-specific parameters. I wanted the base class's method to either be "return false" (never merge, always correct even if the subclass fails to provide the method) or to be pure virtual (force the subclasses to provide the method). And yet, I still needed a way for the subclasses to say "and also check the stuff from the parent class". So that's how I ended up with a pure virtual mergeable() in the base class, and a separate method called base_mergeable(). If you have a more elegant idea, I'm all ears. -- Larry Gritz l...@... |
|
Chris Foster <chri...@...>
On Fri, Mar 26, 2010 at 1:08 PM, Larry Gritz <l...@...> wrote:
On Mar 25, 2010, at 4:38 PM, <aco...@...> <aco...@...> wrote:Actually, it's possible to provide a base class implementation of a pureBut then if somebody forgets to provide a closure subclass with a mergeable virtual function for exactly the purpose of forcing an override while providing some default behaviour (how obtuse!). The following compiles: struct A { virtual int foo() = 0; }; int A::foo() { return 42; } struct B : public A { virtual int foo() { return A::foo(); } }; I'm not sure I'd claim this is any more elegant ;-) One alternative which might be nicer (but OTOH not fully overridable) is to keep the two-method design but invert it - have the base closure mergeable() call the child class version; something like class ClosurePrimitive { public: bool mergeable (const ClosurePrimitive *other) const; { bool base_mergeable = /* stuff from current base_mergeable () */; return base_mergeable && derived_mergeable(other); }; //... protected: virtual bool derived_mergeable (const ClosurePrimitive *other) const = 0; }; that way the child classes can't forget to call the base_mergeable() logic. ~Chris |
|
cku...@...
I second Chris's suggestion of the "inverted" two method setup.
http://codereview.appspot.com/766041/show |
|
cku...@...
http://codereview.appspot.com/766041/diff/1/7
File src/liboslexec/bsdf_diffuse.cpp (right): http://codereview.appspot.com/766041/diff/1/7#newcode51 src/liboslexec/bsdf_diffuse.cpp:51: return m_N == comp->m_N && base_mergeable(other); What about the sidedness parameter in the BSDFClosure class? It doesn't seem to be checked. http://codereview.appspot.com/766041/diff/1/3 File src/liboslexec/closure.cpp (right): http://codereview.appspot.com/766041/diff/1/3#newcode154 src/liboslexec/closure.cpp:154: c.weight *= w; It is still possible to end up with 0 weights here: Ci = diffuse(N); Ci *= color(1, 0, 0); Ci *= color(0, 1, 0); (not sure if this is a problem, but we should remember the code doesn't guarantee the weights to be non-zero) http://codereview.appspot.com/766041/show |
|
aco...@...
Just to give another alternative, leave it as it is but make
base_mergeable virtual so we allow for chained method call on the one too. So ClosurePrimitive would have one and BSDFClosure another (doing the sidedness check) that would in addition call the parent. http://codereview.appspot.com/766041/show |
|