0

How do I achieve the desired output via suitable modification of any code except Derived::Derived()?

#include<iostream>
std::ostream& o = std::cout;

struct Base
{
    void sanitycheck() { o << "base checks\n"; }
    Base() { o << "make base\n"; }
};

// Code of struct Derived shall remain unaltered
struct Derived : Base 
{
    Derived() { o << "make derived\n"; }
};

// Dummy might help?
struct Dummy
{
    Base& base;
    Dummy(Base& base) :base(base) {}
    ~Dummy() { base.sanitycheck(); }
};

int main()
{
    Derived x;
    /* desired output:
    make base
    make derived
    base checks     // <-- missing piece
    */
}

Background: Base is in a library. Derived is user-supplied. Sanity checks can help mitigate user errors.

JeJo
  • 30,635
  • 6
  • 49
  • 88
  • 1
    Off topic, but please note that the "alias" `o` for `std::cout` will likely not pass any code-review. It's a bad habit, that doesn't save you as much as you think in typing speed. – Some programmer dude Aug 13 '23 at 10:03

2 Answers2

2

If I understood your requirement correctly, you are missing only one line ?

Derived x;
Dummy x_dummy{x};   // Missing line

See demo

Read more: What is meant by Resource Acquisition is Initialization (RAII)?

JeJo
  • 30,635
  • 6
  • 49
  • 88
  • I am sorry I failed to say that I also did not want to change the main. I implicitly assumed the main to be user code as well. My apologies. – Darika Ranganathan Aug 13 '23 at 10:07
  • 1
    @DarikaRanganathan Without `Dummy` to be called + without the `Derived` to be modified, I don't see a possibility here. You may want to wrap the above at least to a factory `make_dervied()`. Something like: https://gcc.godbolt.org/z/T5rn6rnM6 – JeJo Aug 13 '23 at 10:12
1

You cannot. Best you can do is provide a function to create the object:

template <std::derived_from<Base> T, typename... Args>
auto make_checked(Args&&... args) -> T {
    T object(std::forward<Args>(args)...);
    object.sanitycheck();
    return object;
}

int main(){
    auto x = make_checked<Derived>();
}

Demo

A decent compiler will use NRVO so no copy or move is performed. Otherwise, the object will be moved (or copied if it is not movable). You can force the type to be movable if needed:

template <std::derived_from<Base> T, typename... Args>
auto make_checked(Args&&... args) -> T requires(std::movable<T>) { ... }
Nelfeal
  • 12,593
  • 1
  • 20
  • 39