In our code with have a class hierarchy with virtual functions. We have different
“diagrams” which produce a fixed bunch of numbers based on the same sort of parameters.
The details are different, but the behavior is the same.
We are happy with the dynamic polymorphism as a pattern, we are not so fond of all the
boilerplate code that we have to write in C++11 in order to achieve it. Mostly I am
frustrated by the repetition in the constructors.
The class hierarchy looks as follows:
There is one base, two intermediate and a lot of children. The base and the intermediate
have non-trivial constructors, the children do not require any more parameters. Yet we
have to produce a constructor in the children because the default constructor would not
properly construct the intermediate.
This is the code, stripped down to constructors, destructors and members only. The
Diagram class:
class Diagram {
public:
Diagram(std::vector<CorrInfo> const &corr_lookup)
: corr_lookup_(corr_lookup) {}
virtual ~Diagram() {}
private:
std::vector<CorrInfo> const &corr_lookup_;
};
The intermediate DiagramNumeric<> class:
template <typename Numeric_>
class DiagramNumeric : public Diagram {
public:
using Numeric = Numeric_;
DiagramNumeric(std::vector<CorrInfo> const &_corr_lookup,
std::string const &output_path,
std::string const &output_filename,
int const Lt)
: Diagram(_corr_lookup),
output_path_(output_path),
output_filename_(output_filename),
Lt_(Lt),
correlator_(corr_lookup().size(), std::vector<Numeric>(Lt, Numeric{})),
c_(omp_get_max_threads(),
std::vector<std::vector<Numeric>>(
Lt, std::vector<Numeric>(corr_lookup().size(), Numeric{}))) {}
private:
std::string const &output_path_;
std::string const &output_filename_;
int const Lt_;
std::vector<std::vector<Numeric>> correlator_;
std::vector<std::vector<std::vector<Numeric>>> c_;
};
And one of the children, here C2c:
class C2c : public DiagramNumeric<cmplx> {
public:
C2c(std::vector<CorrInfo> const &corr_lookup,
std::string const &output_path,
std::string const &output_filename,
int const Lt);
};
C2c::C2c(std::vector<CorrInfo> const &corr_lookup,
std::string const &output_path,
std::string const &output_filename,
int const Lt)
: DiagramNumeric<cmplx>(corr_lookup, output_path, output_filename, Lt) {}
When I need to add another argument to the constructor of the intermediate, I have to
change the DiagramNumeric<> declaration, and every child declaration and definition.
This makes 2 * N + 1 changes with N children and feels awful.
I thought about making a struct as DiagramNumeric<>::CtorParams and that is just
passed through. The client code where the C2c is instantiated needs to be adapted, but
we actually pass only different corr_lookup parameters, the remaining three are always
the same.
Is there some mechanism with which we can cut away a significant portion of this
boilerplate code?
We are happy with the dynamic polymorphism as a pattern,.... I am
frustrated by the repetition in the constructors.
This isn't some c++11 fault. The issue come directly from dynamic polymorphism. And particularly from the fact that each child class is required to construct its parents.
The alternative you have is dependency injection + static polymorphism :
You have classes and methods taking a Diagram template as argument
You don't have a Diagram class anymore (static polymorphism)
C2c and the other classes don't construct a DiagramNumeric<cmplx> anymore, but merely receive one as argument which is copied to a member variable. (dependency injection)
You will end up with
class C2c {
public:
explicit C2c(const DiagramNumeric<cmplx> &diagram_numeric)
: diagram_numeric_(diagram_numeric) {}
private :
DiagramNumeric<cmplx> diagram_numeric_;
};
Let say you want to add another argument. In the best case, that's a O(1) change in terms of dependent classes. In the worst case, it's back to 2*N+1 changes if you have a builder function such as
C2c build(std::vector<CorrInfo> const &corr_lookup,
std::string const &output_path,
std::string const &output_filename,
int const Lt)
{
return C2c(DiagramNumeric<cmplx>(corr_lookup, output_path, output_filename, Lt));
}
Related
first post, so hopefully not violating any etiquette. Feel free to give suggestions for making the question better.
I've seen a few posts similar to this one: Check if a class has a member function of a given signature, but none do quite what I want. Sure it "works with polymorphism" in the sense that it can properly check subclass types for the function that comes from a superclass, but what I'd like to do is check the object itself and not the class. Using some (slightly tweaked) code from that post:
// Somewhere in back-end
#include <type_traits>
template<typename, typename T>
struct HasFunction {
static_assert(integral_constant<T, false>::value,
"Second template parameter needs to be of function type."
);
};
template<typename C, typename Ret, typename... Args>
class HasFunction<C, Ret(Args...)> {
template<typename T>
static constexpr auto check(T*) -> typename is_same<
decltype(declval<T>().myfunc(declval<Args>()...)), Ret>::type;
template<typename>
static constexpr false_type check(...);
typedef decltype(check<C>(0)) type;
public:
static constexpr bool value = type::value;
};
struct W {};
struct X : W { int myfunc(double) { return 42; } };
struct Y : X {};
I'd like to have something like the following:
// somewhere else in back-end. Called by client code and doesn't know
// what it's been passed!
template <class T>
void DoSomething(T& obj) {
if (HasFunction<T, int(double)>::value)
cout << "Found it!" << endl;
// Do something with obj.myfunc
else cout << "Nothin to see here" << endl;
}
int main()
{
Y y;
W* w = &y; // same object
DoSomething(y); // Found it!
DoSomething(*w); // Nothin to see here?
}
The problem is that the same object being viewed polymorphically causes different results (because the deduced type is what is being checked and not the object). So for example, if I was iterating over a collection of W*'s and calling DoSomething I would want it to no-op on W's but it should do something for X's and Y's. Is this achievable? I'm still digging into templates so I'm still not quite sure what's possible but it seems like it isn't. Is there a different way of doing it altogether?
Also, slightly less related to that specific problem: Is there a way to make HasFunction more like an interface so I could arbitrarily check for different functions? i.e. not have ".myfunc" concrete within it? (seems like it's only possible with macros?) e.g.
template<typename T>
struct HasFoo<T> : HasFunction<T, int foo(void)> {};
int main() {
Bar b;
if(HasFoo<b>::value) b.foo();
}
Obviously that's invalid syntax but hopefully it gets the point across.
It's just not possible to perform deep inspection on a base class pointer in order to check for possible member functions on the pointed-to type (for derived types that are not known ahead of time). Even if we get reflection.
The C++ standard provides us no way to perform this kind of inspection, because the kind of run time type information that is guaranteed to be available is very limited, basically relegated to the type_info structure.
Your compiler/platform may provide additional run-time type information that you can hook into, although the exact types and machinery used to provide RTTI are generally undocumented and difficult to examine (This article by Quarkslab attempts to inspect MSVC's RTTI hierarchy)
For example, I cannot write this:
class A
{
vector<int> v(12, 1);
};
I can only write this:
class A
{
vector<int> v1{ 12, 1 };
vector<int> v2 = vector<int>(12, 1);
};
Why is there a difference between these two declaration syntaxes?
The rationale behind this choice is explicitly mentioned in the related proposal for non static data member initializers :
An issue raised in Kona regarding scope of identifiers:
During discussion in the Core Working Group at the September ’07 meeting in Kona, a question arose about the scope of identifiers in the initializer. Do we want to allow class scope with the possibility of forward lookup; or do we want to require that the initializers be well-defined at the point that they’re parsed?
What’s desired:
The motivation for class-scope lookup is that we’d like to be able to put anything in a non-static data member’s initializer that we could put in a mem-initializer without significantly changing the semantics (modulo direct initialization vs. copy initialization):
int x();
struct S {
int i;
S() : i(x()) {} // currently well-formed, uses S::x()
// ...
static int x();
};
struct T {
int i = x(); // should use T::x(), ::x() would be a surprise
// ...
static int x();
};
Problem 1:
Unfortunately, this makes initializers of the “( expression-list )” form ambiguous at the time that the declaration is being parsed:
struct S {
int i(x); // data member with initializer
// ...
static int x;
};
struct T {
int i(x); // member function declaration
// ...
typedef int x;
};
One possible solution is to rely on the existing rule that, if a declaration could be an object or a function, then it’s a function:
struct S {
int i(j); // ill-formed...parsed as a member function,
// type j looked up but not found
// ...
static int j;
};
A similar solution would be to apply another existing rule, currently used only in templates, that if T could be a type or something else, then it’s something else; and we can use “typename” if we really mean a type:
struct S {
int i(x); // unabmiguously a data member
int j(typename y); // unabmiguously a member function
};
Both of those solutions introduce subtleties that are likely to be misunderstood by many users (as evidenced by the many questions on comp.lang.c++ about why “int i();” at block scope doesn’t declare a default-initialized int).
The solution proposed in this paper is to allow only initializers of the “= initializer-clause” and “{ initializer-list }” forms. That solves the ambiguity problem in most cases, for example:
HashingFunction hash_algorithm{"MD5"};
Here, we could not use the = form because HasningFunction’s constructor is explicit.
In especially tricky cases, a type might have to be mentioned twice. Consider:
vector<int> x = 3; // error: the constructor taking an int is explicit
vector<int> x(3); // three elements default-initialized
vector<int> x{3}; // one element with the value 3
In that case, we have to chose between the two alternatives by using the appropriate notation:
vector<int> x = vector<int>(3); // rather than vector<int> x(3);
vector<int> x{3}; // one element with the value 3
Problem 2:
Another issue is that, because we propose no change to the rules for initializing static data members, adding the static keyword could make a well-formed initializer ill-formed:
struct S {
const int i = f(); // well-formed with forward lookup
static const int j = f(); // always ill-formed for statics
// ...
constexpr static int f() { return 0; }
};
Problem 3:
A third issue is that class-scope lookup could turn a compile-time error into a run-time error:
struct S {
int i = j; // ill-formed without forward lookup, undefined behavior with
int j = 3;
};
(Unless caught by the compiler, i might be intialized with the undefined value of j.)
The proposal:
CWG had a 6-to-3 straw poll in Kona in favor of class-scope lookup; and that is what this paper proposes, with initializers for non-static data members limited to the “= initializer-clause” and “{ initializer-list }” forms.
We believe:
Problem 1: This problem does not occur as we don’t propose the () notation. The = and {} initializer notations do not suffer from this problem.
Problem 2: adding the static keyword makes a number of differences, this being the least of them.
Problem 3: this is not a new problem, but is the same order-of-initialization problem that already exists with constructor initializers.
One possible reason is that allowing parentheses would lead us back to the most vexing parse in no time. Consider the two types below:
struct foo {};
struct bar
{
bar(foo const&) {}
};
Now, you have a data member of type bar that you want to initialize, so you define it as
struct A
{
bar B(foo());
};
But what you've done above is declare a function named B that returns a bar object by value, and takes a single argument that's a function having the signature foo() (returns a foo and doesn't take any arguments).
Judging by the number and frequency of questions asked on StackOverflow that deal with this issue, this is something most C++ programmers find surprising and unintuitive. Adding the new brace-or-equal-initializer syntax was a chance to avoid this ambiguity and start with a clean slate, which is likely the reason the C++ committee chose to do so.
bar B{foo{}};
bar B = foo();
Both lines above declare an object named B of type bar, as expected.
Aside from the guesswork above, I'd like to point out that you're doing two vastly different things in your example above.
vector<int> v1{ 12, 1 };
vector<int> v2 = vector<int>(12, 1);
The first line initializes v1 to a vector that contains two elements, 12 and 1. The second creates a vector v2 that contains 12 elements, each initialized to 1.
Be careful of this rule - if a type defines a constructor that takes an initializer_list<T>, then that constructor is always considered first when the initializer for the type is a braced-init-list. The other constructors will be considered only if the one taking the initializer_list is not viable.
if you do this:
constexpr int LEN = 100;
LEN variable defined as const without need of typing const keyword.
It also have static storage, without need to type static keyword.
From the other hand, if we do same in class:
struct A{
constexpr static int SIZE = 100;
};
SIZE is still defined as const without need of typing const keyword,
However SIZE is not static data member.
You need to type static explicitly. If you don't there will be compilation error.
Question is:
What is the reason of need to explicitly type static?
static doesn't have same signification in both context :
for LEN, static means "only available in this compilation unit", so only internal linkage. It's a storage specifier
for A::SIZE, static means "it's a class member", so not bound to specific instances
constexpr in class context can refer to instance or class member or function, so compiler can't determine at your place if it's static or not, ie bound or not to a specific instance. It's same reasoning as const specifier. But, as you can imagine, it's a non-sense to have a non-static constexpr member, so it's forbidden. Example :
class A
{
int a;
constexpr A(int value): a(value) {}
// constexpr bound to a specific instance
constexpr int getDouble() const
{ return a*2; }
// constexpr not bound to a specific instance
static constexpr int getDouble(int b)
{ return b*2; }
}
constexpr in global context refers to something which will be calculated at compile time (or, for function, if not possible to calculate at compile time, which will be inlined), so no need of external linkage and so, comparable behavior as a static global variable or function (only comparable because, with compile time calculation or inlining, you also don't need internal linkage)
constexpr int a = 5; // Will be replace everywhere by value
/* If b is constexpr, calcul are done at compile time and result will be used
* else double is inlined, so no need of linkage at all
*/
constexpr int getDouble(int b)
{ return b * 2; }
constexpr should not imply static, because having constexpr
without static makes sense. Consider:
#include <iostream>
struct Dim
{
constexpr Dim(int a,int b) : a(a), b(b) {}
constexpr int Prod() const { return a*b; }
int a,b;
};
int main()
{
constexpr Dim sz(3,4);
int arr[ sz.Prod() ];
std::cout << sizeof(arr) << std::endl;
}
It should also not imply static outside of class definition
since static there means 'local to translation unit' and constexpr
does not require that.
I think you are confused about what static means at global scope, and your question is based on that misunderstanding.
LEN variable defined as const without need of typing const keyword.
Of course constexpr implies const, that shouldn't be surprising.
It also have static storage, without need to type static keyword.
N.B. a global variable always has static storage, because its lifetime is global. Adding the static keyword does not change that, what it does is give it internal linkage meaning it is not accessible by name outside the current translation unit.
That's the same rule for constexpr and const on global variables: a namespace-scope const variable implicitly has internal linkage (which is one of the many meanings of "static").
But a class-scope const variable does not have internal linkage, even if you add static to it. Marking a variable static means something completely different at namespace-scope and class-scope. It doesn't make sense to automatically add static to class members marked const or constexpr because that would mean something completely different than it does to variables at namespace-scope.
So constexpr implies const (obviously), and at namespace scope const implies internal linkage.
At class scope constexpr still implies const, but that doesn't have any effect on whether a member variable is a "class variable" or an "instance variable".
I often use the "dependency injection" pattern in my projects. In C++ it is easiest to implement by passing around raw pointers, but now with C++11, everything in high-level code should be doable with smart pointers. But what is the best practice for this case? Performance is not critical, a clean and understandable code matters more to me now.
Let me show a simplified example. We have an algorithm that uses distance calculations inside. We want to be able to replace this calculation with different distance metrics (Euclidean, Manhattan, etc.). Our goal is to be able to say something like:
SomeAlgorithm algorithmWithEuclidean(new EuclideanDistanceCalculator());
SomeAlgorithm algorithmWithManhattan(new ManhattanDistanceCalculator());
but with smart pointers to avoid manual new and delete.
This is a possible implementation with raw pointers:
class DistanceCalculator {
public:
virtual double distance(Point p1, Point p2) = 0;
};
class EuclideanDistanceCalculator {
public:
virtual double distance(Point p1, Point p2) {
return sqrt(...);
}
};
class ManhattanDistanceCalculator {
public:
virtual double distance(Point p1, Point p2) {
return ...;
}
};
class SomeAlgorithm {
DistanceCalculator* distanceCalculator;
public:
SomeAlgorithm(DistanceCalculator* distanceCalculator_)
: distanceCalculator(distanceCalculator_) {}
double calculateComplicated() {
...
double dist = distanceCalculator->distance(p1, p2);
...
}
~SomeAlgorithm(){
delete distanceCalculator;
}
};
Let's assume that copying is not really an issue, and if we didn't need polymorphism we would just pass the DistanceCalculator to the constructor of SomeAlgorithm by value (copying). But since we need to be able to pass in different derived instances (without slicing), the parameter must be either a raw pointer, a reference or a smart pointer.
One solution that comes to mind is to pass it in by reference-to-const and encapsulate it in a std::unique_ptr<DistanceCalculator> member variable. Then the call would be:
SomeAlgorithm algorithmWithEuclidean(EuclideanDistance());
But this stack-allocated temporary object (rvalue-reference?) will be destructed after this line. So we'd need some copying to make it more like a pass-by-value. But since we don't know the runtime type, we cannot construct our copy easily.
We could also use a smart pointer as the constructor parameter. Since there is no issue with ownership (the DistanceCalculator will be owned by SomeAlgorithm) we should use std::unique_ptr. Should I really replace all of such constructor parameters with unique_ptr? it seems to reduce readability. Also the user of SomeAlgorithm must construct it in an awkward way:
SomeAlgorithm algorithmWithEuclidean(std::unique_ptr<DistanceCalculator>(new EuclideanDistance()));
Or should I use the new move semantics (&&, std::move) in some way?
It seems to be a pretty standard problem, there must be some succinct way to implement it.
If I wanted to do this, the first thing I'd do is kill your interface, and instead use this:
SomeAlgorithm(std::function<double(Point,Point)> distanceCalculator_)
type erased invocation object.
I could do a drop-in replacement using your EuclideanDistanceCalculator like this:
std::function<double(Point,Point)> UseEuclidean() {
auto obj = std::make_shared<EuclideanDistance>();
return [obj](Point a, Point b)->double {
return obj->distance( a, b );
};
}
SomeAlgorithm foo( UseEuclidean() );
but as distance calculators rarely require state, we could do away with the object.
With C++1y support, this shortens to:
std::function<double(Point,Point>> UseEuclidean() {
return [obj = std::make_shared<EuclideanDistance>()](Point a, Point b)->double {
return obj->distance( a, b );
};
}
which as it no longer requires a local variable, can be used inline:
SomeAlgorithm foo( [obj = std::make_shared<EuclideanDistance>()](Point a, Point b)->double {
return obj->distance( a, b );
} );
but again, the EuclideanDistance doesn't have any real state, so instead we can just
std::function<double(Point,Point>> EuclideanDistance() {
return [](Point a, Point b)->double {
return sqrt( (b.x-a.x)*(b.x-a.x) + (b.y-a.y)*(b.y*a.y) );
};
}
If we really don't need movement but we do need state, we can write a unique_function< R(Args...) > type that does not support non-move based assignment, and store one of those instead.
The core of this is that the interface DistanceCalculator is noise. The name of the variable is usually enough. std::function< double(Point,Point) > m_DistanceCalculator is clear in what it does. The creator of the type-erasure object std::function handles any lifetime management issues, we just store the function object by value.
If your actual dependency injection is more complicated (say multiple different related callbacks), using an interface isn't bad. If you want to avoid copy requirements, I'd go with this:
struct InterfaceForDependencyStuff {
virtual void method1() = 0;
virtual void method2() = 0;
virtual int method3( double, char ) = 0;
virtual ~InterfaceForDependencyStuff() {}; // optional if you want to do more work later, but probably worth it
};
then, write up your own make_unique<T>(Args&&...) (a std one is coming in C++1y), and use it like this:
Interface:
SomeAlgorithm(std::unique_ptr<InterfaceForDependencyStuff> pDependencyStuff)
Use:
SomeAlgorithm foo(std::make_unique<ImplementationForDependencyStuff>( blah blah blah ));
If you don't want virtual ~InterfaceForDependencyStuff() and want to use unique_ptr, you have to use a unique_ptr that stores its deleter (by passing in a stateful deleter).
On the other hand, if std::shared_ptr already comes with a make_shared, and it stores its deleter statefully by default. So if you go with shared_ptr storage of your interface, you get:
SomeAlgorithm(std::shared_ptr<InterfaceForDependencyStuff> pDependencyStuff)
and
SomeAlgorithm foo(std::make_shared<ImplementationForDependencyStuff>( blah blah blah ));
and make_shared will store a pointer-to-function that deletes ImplementationForDependencyStuff that will not be lost when you convert it to a std::shared_ptr<InterfaceForDependencyStuff>, so you can safely lack a virtual destructor in InterfaceForDependencyStuff. I personally would not bother, and leave virtual ~InterfaceForDependencyStuff there.
In most cases you don't want or need ownership transfer, it makes code harder to understand and less flexible (moved-from objects can't be reused). The typical case would be to keep ownership with the caller:
class SomeAlgorithm {
DistanceCalculator* distanceCalculator;
public:
explicit SomeAlgorithm(DistanceCalculator* distanceCalculator_)
: distanceCalculator(distanceCalculator_) {
if (distanceCalculator == nullptr) { abort(); }
}
double calculateComplicated() {
...
double dist = distanceCalculator->distance(p1, p2);
...
}
// Default special members are fine.
};
int main() {
EuclideanDistanceCalculator distanceCalculator;
SomeAlgorithm algorithm(&distanceCalculator);
algorithm.calculateComplicated();
}
Raw pointers are fine to express non-ownership. If you prefer you can use a reference in the constructor argument, it makes no real difference. However, don't use a reference as data member, it makes the class unnecessarily unassignable.
The down side of just using any pointer (smart or raw), or even an ordinary C++ reference, is that they allow calling non-const methods from a const context.
For stateless classes with a single method that is a non-issue, and std::function is a good alternative, but for the general case of classes with state or multiple methods I propose a wrapper similar but not identical to std::reference_wrapper (which lacks the const safe accessor).
template<typename T>
struct NonOwningRef{
NonOwningRef() = delete;
NonOwningRef(T& other) noexcept : ptr(std::addressof(other)) { };
NonOwningRef(const NonOwningRef& other) noexcept = default;
const T& value() const noexcept{ return *ptr; };
T& value() noexcept{ return *ptr; };
private:
T* ptr;
};
usage:
class SomeAlgorithm {
NonOwningRef<DistanceCalculator> distanceCalculator;
public:
SomeAlgorithm(DistanceCalculator& distanceCalculator_)
: distanceCalculator(distanceCalculator_) {}
double calculateComplicated() {
double dist = distanceCalculator.value().distance(p1, p2);
return dist;
}
};
Replace T* with unique_ptr or shared_ptr to get owning versions. In this case, also add move construction, and construction from any unique_ptr<T2> or shared_ptr<T2> ).
I have the boost::variant over set of non-default constructible (and maybe even non-moveable/non-copyable and non-copy/move constructible) classes with essentialy different non-default constructor prototypes, as shown below:
#include <boost/variant.hpp>
#include <string>
#include <list>
struct A { A(int) { ; } };
struct B { B(std::string) { ; } };
struct C { C(int, std::string) { ; } };
using V = boost::variant< A const, B const, C const >;
using L = std::list< V >;
int main()
{
L l;
l.push_back(A(1)); // an extra copy/move operation
l.push_back(B("2")); // an extra copy/move operation
l.push_back(C(3, "3")); // an extra copy/move operation
l.emplace_back(4);
l.emplace_back(std::string("5"));
// l.emplace_back(3, std::string("3")); // error here
return 0;
}
I expect, that std::list::emplace_back allows me to construct-and-insert (in single operation) new objects (of all the A, B, C types) into list, even if they have T & operator = (T const &) = delete;/T & operator = (T &&) = delete; and T(T const &) = delete;/T(T &&) = delete;. But what should I do, if constructor is a non-conversion one? I.e. have more, than one parameter. Or what I should to do if two different variant's underlying types have ambiguous constructor prototypes? In my opinion, this is the defect of implementation of the boost::variant library in the light of the new features of C++11 standard, if any at all can be applyed to solve the problem.
I specifically asked about std::list and boost::variant in superposition, because they are both internally implement the pimpl idiom in some form, as far as I know (say, boost::variant currently designed by means of temporary heap backup approach).
emplace can only call the constructors of the type in question. And boost::variant's constructors only take single objects which are unambiguously convertible to one of the variant's types.
variant doesn't forward parameters arbitrarily to one of its bounded types. It just takes a value. A single value that it will try to convert to one of the bounded types.
So you're going to have to construct an object and then copy that into the variant.
Assuming you can modify your "C" class, you could give it an additional constructor that takes a single tuple argument.