Situation
I use GCC 5.3.0 provided by Mingw on Window 7, and gtest to implement and run unit tests.
In my project, I have a hierarchy of computers, which implements the interface Computer
as below :
class Dataset; // Not
// Interface Computer
class Computer {
public:
// Destructor virtual to enable vmap
virtual ~Computer() noexcept = default;
// Pure virtual fonctions
virtual bool preCompute(Dataset &datas) const = 0;
virtual void compute(Dataset &datas) const = 0;
};
I provide an abstract implementation of this interface as ChainableComputer
, which implements another interface (Chainable
) and a default implementation of precompute
. See below.
class ChainableComputer : public Computer, public Chainable {
public:
bool preCompute(Dataset &dataset) const override;
};
Those classes are in a namespace, called core
, and packaged in core.dll
In another dll, i have implementation of ChainableComputer
in another namespace domain
.
Some of the implementation are simple, and don't have any thing to do in preCompute, so, they implements compute with the same way :
class SomeComputerImpl : public ChainableComputer{
/// ...
void compute(Dataset &datas) const override final{
auto result = preCompute(datas);
if(!result){
throw;
}
}
};
This code was spreading so i decided to refactor and add a protected method in Computer :
class Computer {
/// ...
protected:
// Helper function for some implementations of Computer
void doPrecomputeOrThrow(Dataset &datas) const{
auto result = preCompute(datas);
if(!result){
throw;
}
}
}
I don't wan't this behavior to be the default for computer, but it give me the possibility to change implementation of these computer as below :
class SomeComputerImpl : public ChainableComputer{
/// ...
void compute(Dataset &datas) const override final{
doPrecomputeOrThrow(Dataset &datas);
}
};
It compiles and works well in the application and in the unit test... if i compile and run in Release mode.
If I choose Debug, the compiling works, the application work, but the tests don't.
I try to understand what it could happen, but I cannot figure out what could be wrong. I guess it has something to with the linker, and the fact that the interface, an abstract implementation and the concrete implementation are in separates DLL, and that we run this stuff in another executable...
What i already try
- Implement a
ChainableComputer
directly in the test => works as expected
- Plays with
inline
or __attribute__(always_inline)
on doPrecomputeOrThrow
=> no effect
- Implementing
doPrecomputeOrThrow
in namespace (passing Computer * as argument), in core.dll => no effect
- Implementing
doPrecomputeOrThrow
in namespace (passing Computer * as argument), in domain.dll => works as expected
- Implementing
doPrecomputeOrThrow
as template in class or in namespace, with Computer
as template parameter (see below) => works as expected
-
Implementing doPrecomputeOrThrow
as template in class, with Dataset
as template parameter (see below) => no effect
/// Template which works, as member of Computer
(static or not), or /// in namespace template void doPrecomputerOrThrows(AComputer * c, Dataset& datas);
/// Template which doesn't work, as member of Computer
template void doPrecomputerOrThrows(ADataset& datas);
The Question
There is someone who have an idea of what happens ?