Determine whether a constructor of an abstract base class is noexcept? - c++

In C++11 and later, how to determine whether a constructor of an abstract base class is noexcept? The following methods don't work:
#include <new>
#include <type_traits>
#include <utility>
struct Base { Base() noexcept; virtual int f() = 0; };
// static assertion fails, because !std::is_constructible<Base>::value:
static_assert(std::is_nothrow_constructible<Base>::value, "");
// static assertion fails, because !std::is_constructible<Base>::value:
static_assert(std::is_nothrow_default_constructible<Base>::value, "");
// invalid cast to abstract class type 'Base':
static_assert(noexcept(Base()), "");
// invalid new-expression of abstract class type 'Base'
static_assert(noexcept(new (std::declval<void *>()) Base()), "");
// cannot call constructor 'Base::Base' directly:
static_assert(noexcept(Base::Base()), "");
// invalid use of 'Base::Base':
static_assert(noexcept(std::declval<Base &>().Base()), "");
A simple use for this would be:
int g() noexcept;
struct Derived: Base {
template <typename ... Args>
Derived(Args && ... args)
noexcept(noexcept(Base(std::forward<Args>(args)...)))
: Base(std::forward<Args>(args)...)
, m_f(g())
{}
int f() override;
int m_f;
};
Any ideas about how to archieve this or whether it is possible at all without modifying the abstract base class?
PS: Any references to ISO C++ defect reports or work-in-progress is also welcome.
EDIT: As was pointed out twice, defaulting the Derived constructors with = default makes noexcept being inherited. But this does not solve the problem for the general case.

[UPDATE: IT'S WORTH JUMPING TO THE EDIT SECTION]
Ok, I found a solution, even though it doesn't compile with all the compilers because of a bug in GCC (see this question for further details).
The solution is based on inherited constructors and the way functions calls are resolved.
Consider the following example:
#include <utility>
#include <iostream>
struct B {
B(int y) noexcept: x{y} { }
virtual void f() = 0;
int x;
};
struct D: public B {
private:
using B::B;
public:
template<typename... Args>
D(Args... args)
noexcept(noexcept(D{std::forward<Args>(args)...}))
: B{std::forward<Args>(args)...}
{ }
void f() override { std::cout << x << std::endl; }
};
int main() {
B *b = new D{42};
b->f();
}
I guess it's quite clear.
Anyway, let me know if you find that something needs more details and I'll be glad to update the answer.
The basic idea is that we can inherit directly the noexcept definition from the base class along with its constructors, so that we have no longer to refer to that class in our noexcept statements.
Here you can see the above mentioned working example.
[EDIT]
As from the comments, the example suffers of a problem if the constructors of the base class and the derived one have the same signature.
Thank to Piotr Skotnicki for having pointed it out.
I'm going to mention those comments and I'll copy and paste the code proposed along with them (with a mention of the authors where needed).
First of all, here we can see that the example as it is does not work as expected (thanks to Piotr Skotnicki for the link).
The code is almost the same previously posted, so it doesn't worth to copy and paste it here.
Also, from the same author, it follows an example that shows that the same solution works as expected under certain circumstances (see the comments for furter details):
#include <utility>
#include <iostream>
struct B {
B(int y) noexcept: x{y}
{
std::cout << "B: Am I actually called?\n";
}
virtual void f() = 0;
int x;
};
struct D: private B {
private:
using B::B;
public:
template<typename... Args>
D(int a, Args&&... args)
noexcept(noexcept(D{std::forward<Args>(args)...}))
: B{std::forward<Args>(args)...}
{
std::cout << "D: Am I actually called?\n";
}
void f() override { std::cout << x << std::endl; }
};
int main()
{
D* d = new D{71, 42};
(void)d;
}
Also, I propose an alternative solution that is a bit more intrusive and is based on the idea for which the std::allocator_arg_t stands for, that is also the same proposed by Piotr Skotnicki in a comment:
it's enough if derived class' constructor wins in overload resolution.
It follows the code mentioned here:
#include <utility>
#include <iostream>
struct B {
B(int y) noexcept: x{y}
{
std::cout << "B: Am I actually called?\n";
}
virtual void f() = 0;
int x;
};
struct D: public B {
private:
using B::B;
public:
struct D_tag { };
template<typename... Args>
D(D_tag, Args&&... args)
noexcept(noexcept(D{std::forward<Args>(args)...}))
: B{std::forward<Args>(args)...}
{
std::cout << "D: Am I actually called?\n";
}
void f() override { std::cout << x << std::endl; }
};
int main()
{
D* d = new D{D::D_tag{}, 42};
(void)d;
}
Thanks once more to Piotr Skotnicki for his help and comments, really appreciated.

Based on skypjack's answer a better solution which does not require a signature change of the Derived constructor would be to define a mock subclass of Base as a private type member of Derived, and use the construction of that in the Derived constructor noexcept specification:
class Derived: Base {
private:
struct MockDerived: Base {
using Base::Base;
// Override all pure virtual methods with dummy implementations:
int f() override; // No definition required
};
public:
template <typename ... Args>
Derived(Args && ... args)
noexcept(noexcept(MockDerived(std::forward<Args>(args)...)))
: Base(std::forward<Args>(args)...)
, m_f(g())
{}
int f() override { return 42; } // Real implementation
int m_f;
};

A naive but working example would be to introduce a non-virtual base class and export its constructor by means of the using directive. Here is an example:
#include<utility>
struct BaseBase {
BaseBase() noexcept { }
};
struct Base: public BaseBase {
using BaseBase::BaseBase;
virtual int f() = 0;
};
struct Derived: public Base {
template <typename ... Args>
Derived(Args && ... args)
noexcept(noexcept(BaseBase(std::forward<Args>(args)...)))
: Base(std::forward<Args>(args)...)
{ }
int f() override { }
};
int main() {
Derived d;
d.f();
}

I was facing the same problem and the solution I found was to implement additionnal traits.
You can have a look to my post here.

Related

In pure virtual calls keep CRTP pattern from overflowing [duplicate]

Consider the following standard CRTP example:
#include <iostream>
template<class Derived>
struct Base {
void f() { static_cast<Derived *>(this)->f(); }
void g() { static_cast<Derived *>(this)->g(); }
};
struct Foo : public Base<Foo> {
void f() { std::cout << 42 << std::endl; }
};
int main() {
Foo foo;
foo.f(); // just OK
foo.g(); // this will stack overflow and segfault
}
If this was regular virtual inheritance I could have mark virtual f and g methods as pure like
struct Base {
virtual void f() = 0;
virtual void g() = 0;
};
and get a compile time error about Foo being abstract. But CRTP offers no such protection. Can I implement it somehow? Runtime check is acceptable too. I thought about comparing this->f pointer with static_cast<Derived *>(this)->f, but didn't manage to make it work.
You can assert at compile time that the two pointers to member functions are different, e.g.:
template<class Derived>
struct Base {
void g() {
static_assert(&Derived::g != &Base<Derived>::g,
"Derived classes must implement g().");
static_cast<Derived *>(this)->g();
}
};
Here is another possibility:
#include <iostream>
template<class Derived>
struct Base {
auto f() { return static_cast<Derived *>(this)->f(); }
auto g() { return static_cast<Derived *>(this)->g(); }
};
struct Foo : public Base<Foo> {
void f() { std::cout << 42 << std::endl; }
};
int main() {
Foo foo;
foo.f(); // just OK
foo.g(); // this will not compile
}
For GCC, it gives a pretty clear error message ("error: use of 'auto Base::g() [with Derived = Foo]' before deduction of 'auto'"), while for Clang, it gives a slightly less readable infinitely recursing template instantiation of Base<Foo>::g, with g instantiating itself but eventually ending in an error.
You could use this solution, you can have pure "non-virtual abstract" function, and it maps as much as possible to CRTP this recommendation of H. Sutter:
template<class Derived>
struct Base
{
void f(){static_cast<Derived*>(this)->do_f();}
void g(){static_cast<Derived*>(this)->do_g();}
private:
//Derived must implement do_f
void do_f()=delete;
//do_g as a default implementation
void do_g(){}
};
struct derived
:Base<derived>
{
friend struct Base<derived>;
private:
void do_f(){}
};
You could consider doing something like this instead. You can make Derived a member and either supply it as a template parameter directly each time you instantiate a Base or else use a type alias as I have done in this example:
template<class Derived>
struct Base {
void f() { d.f(); }
void g() { d.g(); }
private:
Derived d;
};
struct FooImpl {
void f() { std::cout << 42 << std::endl; }
};
using Foo = Base<FooImpl>;
int main() {
Foo foo;
foo.f(); // OK
foo.g(); // compile time error
}
Of course Derived is no longer derived so you might pick a better name for it.

Protect CRTP pattern from stack overflowing in "pure virtual" calls

Consider the following standard CRTP example:
#include <iostream>
template<class Derived>
struct Base {
void f() { static_cast<Derived *>(this)->f(); }
void g() { static_cast<Derived *>(this)->g(); }
};
struct Foo : public Base<Foo> {
void f() { std::cout << 42 << std::endl; }
};
int main() {
Foo foo;
foo.f(); // just OK
foo.g(); // this will stack overflow and segfault
}
If this was regular virtual inheritance I could have mark virtual f and g methods as pure like
struct Base {
virtual void f() = 0;
virtual void g() = 0;
};
and get a compile time error about Foo being abstract. But CRTP offers no such protection. Can I implement it somehow? Runtime check is acceptable too. I thought about comparing this->f pointer with static_cast<Derived *>(this)->f, but didn't manage to make it work.
You can assert at compile time that the two pointers to member functions are different, e.g.:
template<class Derived>
struct Base {
void g() {
static_assert(&Derived::g != &Base<Derived>::g,
"Derived classes must implement g().");
static_cast<Derived *>(this)->g();
}
};
Here is another possibility:
#include <iostream>
template<class Derived>
struct Base {
auto f() { return static_cast<Derived *>(this)->f(); }
auto g() { return static_cast<Derived *>(this)->g(); }
};
struct Foo : public Base<Foo> {
void f() { std::cout << 42 << std::endl; }
};
int main() {
Foo foo;
foo.f(); // just OK
foo.g(); // this will not compile
}
For GCC, it gives a pretty clear error message ("error: use of 'auto Base::g() [with Derived = Foo]' before deduction of 'auto'"), while for Clang, it gives a slightly less readable infinitely recursing template instantiation of Base<Foo>::g, with g instantiating itself but eventually ending in an error.
You could use this solution, you can have pure "non-virtual abstract" function, and it maps as much as possible to CRTP this recommendation of H. Sutter:
template<class Derived>
struct Base
{
void f(){static_cast<Derived*>(this)->do_f();}
void g(){static_cast<Derived*>(this)->do_g();}
private:
//Derived must implement do_f
void do_f()=delete;
//do_g as a default implementation
void do_g(){}
};
struct derived
:Base<derived>
{
friend struct Base<derived>;
private:
void do_f(){}
};
You could consider doing something like this instead. You can make Derived a member and either supply it as a template parameter directly each time you instantiate a Base or else use a type alias as I have done in this example:
template<class Derived>
struct Base {
void f() { d.f(); }
void g() { d.g(); }
private:
Derived d;
};
struct FooImpl {
void f() { std::cout << 42 << std::endl; }
};
using Foo = Base<FooImpl>;
int main() {
Foo foo;
foo.f(); // OK
foo.g(); // compile time error
}
Of course Derived is no longer derived so you might pick a better name for it.

Using SFINAE to disable template class member function

Is it possible to use SFINAE and std::enable_if to disable a single member function of a template class?
I currently have a code similar to this:
#include <type_traits>
#include <iostream>
#include <cassert>
#include <string>
class Base {
public:
virtual int f() { return 0; }
};
template<typename T>
class Derived : public Base {
private:
T getValue_() { return T(); }
public:
int f() override {
assert((std::is_same<T, int>::value));
T val = getValue_();
//return val; --> not possible if T not convertible to int
return *reinterpret_cast<int*>(&val);
}
};
template<typename T>
class MoreDerived : public Derived<T> {
public:
int f() override { return 2; }
};
int main() {
Derived<int> i;
MoreDerived<std::string> f;
std::cout << f.f() << " " << i.f() << std::endl;
}
Ideally, Derived<T>::f() should be disabled if T != int. Because f is virtual, Derived<T>::f() gets generated for any instantiation of Derived, even if it is never called.
But the code is used such that Derived<T> (with T != int) never gets created only as a base class of MoreDerived<T>.
So the hack in Derived<T>::f() is necessary to make the program compile; the reinterpret_cast line never gets executed.
You could simply specialize f for int:
template<typename T>
class Derived : public Base {
private:
T getValue_() { return T(); }
public:
int f() override {
return Base::f();
}
};
template <>
int Derived<int>::f () {
return getValue_();
}
No you can't rule out a member function with SFINAE. You could do it with specialisation of your Derived class f member function for convertible Ts to int but that would lead to unnecessary duplication of code. In C++17 however you could solve this with use of if constexpr:
template<typename T> class Derived : public Base {
T getValue_() { return T(); }
public:
int f() override {
if constexpr(std::is_convertible<T, int>::value) return getValue_();
return Base::f();
}
};
Live Demo

Is it possible to pass "this" by default?

Is it possible to pass this by default ?
Here is what I currently have
class A
{
public:
template<typename T>
void dowithT(T t) {}
};
class B
{
public:
A a;
B()
{
//Calling 'dowithT' with 'this'
a.dowithT(this);
}
};
This function requires passing this from the caller of the function every time. So I wondered if there is a way to encapsulate this task, so that you don't need to pass this to dowithT.
I tried to do something like this:
class A
{
public:
// '= this' doesn't compile
template<typename T>
void dowithT(T t = this) {}
};
class B
{
public:
A a;
B()
{
//Calling 'dowithT' without 'this'
a.dowithT();
}
};
Unfortunately, I can't use templates, so my first solution isn't an option.
Is this possible?
Edit: I gave a concrete answer with my own implementation below. Also with a few mor deatils of what I wanted in the end.
TL;DR No, this is not possible.
this is not the same type in every class, you can't generalize it, so no, not possible.
Additionally, what would this be if doWithT() was called from a non-member function? nullptr?
That's why it isn't possible. You have to use a template.
Instead of B having a member of type A, it can inherit from A, and use something like the "curiously recurring template pattern."
If you cannot make class A a template, you can still do it like so:
class A
{
protected:
template <class T>
void dowithT()
{
T* callerthis = static_cast<T*>(this);
// callerthis is the "this" pointer for the inheriting object
cout << "Foo";
}
};
class B : public A
{
public:
B()
{
dowithT<B>();
// Or A::dowithT<B>();
}
};
dowithT() must only be called by an inheriting class (hence I made it protected), with the template parameter the caller's own type, or you'll break everything.
You may achieve exactly what you want by using a private mixin class to provide the dowithT method that takes no arguments:
#include <iostream>
#include <typeinfo>
class A
{
public:
template<typename T>
void dowithT(T* t) {
std::cout << "Hello, World" << typeid(*t).name() << std::endl;
}
};
template<class Owner>
struct calls_a
{
void dowithT()
{
auto p = static_cast<Owner*>(this);
p->a.dowithT(p);
}
};
class B
: private calls_a<B>
{
friend calls_a<B>;
A a;
public:
B()
{
//Calling 'dowithT' with 'this'
dowithT();
}
};
int main()
{
B b;
}
No, it is not possible. There is nothing really special about this when used as an argument to a function taking T* (template or not), it's just a pointer like any other.
this A is different from this B. In your first code, this refers to the caller, while in the second this refers to the callee. Thus what you want to do isnt really possible.
Here's one possibility, which might, or might not suit your needs:
template<typename T>
class A
{
public:
A(T t) : t(t) {}
void dowithT()
{
cout << "Foo";
}
private:
T t;
};
class B
{
public:
A<B*> a;
B() : a(this)
{
a.dowithT();
}
};
You could use a private method in class B that acts as a relay, and use the constant nullptr as a special value for this, if you want to be able to pass other values:
class B
{
public:
A a;
B()
{
//Calling 'dowithT' with 'this'
innerdo();
}
private:
void innerdo(B *p = nullptr) {
if (p == nullptr) p = this;
a.dowithT(p);
}
};
If you only need to pass this it is even simpler
void innerdo() {
a.dowithT(this);
}
After trying out various things you mentioned, I'd like to give my answer/solution to the problem myself to clarify some details:
#include <iostream>
using namespace std;
#include <functional>
template <typename CallerType>
class AFunctionConstructor{
private:
virtual void abstr()
{}
public:
typedef void(CallerType::*CallerTypeFunc)();
function<void()>* constructFunction(CallerTypeFunc func)
{
CallerType* newMe = dynamic_cast<CallerType*> (this);
return new function<void()>(std::bind(func,newMe));
}
};
class A : public function<void()>
{
protected:
public:
A();
A(function<void()>* func) : function<void()>(*func)
{}
};
// now create ressource classes
// they provide functions to be called via an object of class A
class B : public AFunctionConstructor<B>
{
void foo()
{
cout << "Foo";
}
public:
A a;
B() : a(constructFunction(&B::foo)) {}
};
class C : public AFunctionConstructor < C >
{
void bar()
{
cout << "Bar";
}
public:
A a;
C() : a(constructFunction(&C::bar)) {}
};
int main()
{
B b;
C c;
b.a();
c.a();
cout << endl;
A* array[5];
array[0] = &b.a; //different functions with their ressources
array[1] = &c.a;
array[2] = &b.a;
array[3] = &c.a;
array[4] = &c.a;
for (int i = 0; i < 5; i++) //this usability i wanted to provide
{
(*(array[i]))();
}
getchar();
return 0;
}
Output :
FooBar
FooBarFooBarBar
This is as far as i can press it down concerning examples. But i guess this is unsafe code. I stumbled across possible other and simpler ways to achieve this (other uses of std::function and lambdas(which i might have tried to reinvent here partially it seems)).
At first I had tried to pass "this" to the bind function in function<void()>*AFunctionConstructor::constructFunction(CallerTypeFunc func)
,though, which i now get through the dynamic upcast.
Additionally the functionality of AFunctionConstructor was first supposed to be implemented in a Constructor of A.

Replacing non-pure virtual functions with CRTP

I'm writing plugins for an application through its C++ SDK. The mechanism is fairly simple. A plugin provides its functionality through predefined interfaces. This is done by having server classes inherit from one implementation class per interface, which contains either pure vitual functions or non-pure functions with default implementations.
This is very practical as SDK clients only have to override those methods that the plugin requires and/or provide an implementation for the (rare) ones with no default.
What has been bugging me is that everything is known at compile time. The virtual function tables and machinery associated with runtime polymorphism are here only for the sake of providing default implementations.
I'm attempting to remove this overhead while keeping the convenience.
As a (very contrived) example, say I have a couple of servers presenting a single interface (named Blah) consisting of only one method with no default implementation.
// SDK header
struct OldImpl_Blah {
virtual ~OldImpl_Blah() =default;
virtual int mult(int) =0;
};
// plugin source
class OldServer3 : public OldImpl_Blah {
public:
int mult(int i) override { return 3 * i; }
};
class OldServer5 : public OldImpl_Blah {
public:
int mult(int i) override { return 5 * i; }
};
For pure virtual functions, straight forward CRTP works just fine.
// SDK header
template <typename T>
struct NewImpl_Blah {
int mult(int i) { return static_cast<T*>(this)->mult(i); }
};
// plugin source
class NewServer3 : public NewImpl_Blah<NewServer3> {
public:
int mult(int i) { return 3 * i; }
};
class NewServer5 : public NewImpl_Blah<NewServer5> {
public:
int mult(int i) { return 5 * i; }
};
The problem is with non-pure virtual functions, i.e. when there is a default implementation for the method.
// SDK header
struct OldImpl_Blah {
virtual ~OldImpl_Blah() =default;
virtual int mult(int i) { return i; } // default
};
// plugin source
class OldServer3 : public OldImpl_Blah {
public:
int mult(int i) override { return 3 * i; }
};
class OldServer5 : public OldImpl_Blah {
public:
int mult(int i) override { return 5 * i; }
};
I tried to combine CRTP with some expression SFINAE trickery and failed.
I guess what I need is some kind of code dispatching where the base class would either provide a default implementation or forward its arguments to the implementation in the derived class, if it exists.
The problem seems to be that the dispatch should rely on information that is not yet available to the compiler in the base class.
A simple solution would be to just remove the virtual and override keywords in the code. But then the compiler wouldn't check that the function signatures match.
Is there some well known pattern for this situation? Is what I'm asking possible at all?
(Please use small words as my expertise with templates is a bit on the light side. Thanks.)
As always, Yet Another Level of Indirection is the solution. In this particular case, it's the well known technique of public non-virtual functions calling private or protected virtual functions. It have its own uses, independent of what is being discussed here, so check it out regardless. Normally it works like this:
struct OldImpl_Blah {
piblic:
virtual ~OldImpl_Blah() = default;
int mult(int i) { return mult_impl(i); }
protected:
virtual int mult_impl(int i) { return i; }
};
// plugin source
class OldServer3 : public OldImpl_Blah {
protected:
int mult_impl(int i) override { return 3 * i; }
};
With CRTP it's exactly the same:
template <class T>
struct OldImpl_Blah {
piblic:
virtual ~OldImpl_Blah() = default;
int mult(int i) { return static_cast<T*>(this)->mult_impl(i); }
protected:
virtual int mult_impl(int i) { return i; }
};
// plugin source
class OldServer3 : public OldImpl_Blah<OldServer3> {
protected:
int mult_impl(int i) override { return 3 * i; }
};
Disclaimer: CRTP is said to eliminate virtual call overhead by nit requiring functions to be virtual. I don't know if CRTP has any performance benefits when functions are kept virtual.
Consider using something like policy design:
struct DefaultMult {
int mult(int i) { return i; }
};
// SDK header
template <typename MultPolicy = DefaultMult>
struct NewImpl_Blah {
int mult(int i) { return multPolicy.mult(i); }
private:
MultPolicy multPolicy;
};
// plugin source
class NewServer3 {
public:
int mult(int i) { return 3 * i; }
};
class NewServer5 {
public:
int mult(int i) { return 5 * i; }
};
void client() {
NewImpl_Blah<NewServer5> myServer;
}
Also note that in theory using final keyword with override enables compilers to dispatch more optimally than vtable approach. I expect modern compilers to optimise if you use final keyword in your first implementation.
Some helpful refs:
mixin design
For more on policy based design you can watch video or read book / article by Andrei Alexandrescu
To be honest I'm not sure I'd use the following code, but I think it does what the OP is asking for.
This is a minimal, working example:
#include<iostream>
#include<utility>
template<class D>
struct B {
template <typename T>
struct hasFoo {
template<typename C>
static std::true_type check(decltype(&C::foo));
template<typename>
static std::false_type check(...);
static const bool value = decltype(check<T>(0))::value;
};
int foo() {
return B::foo<D>(0, this);
}
private:
template<class T>
static auto foo(int, B* p) -> typename std::enable_if<hasFoo<T>::value, int>::type {
std::cout << "D::foo" << std::endl;
return static_cast<T*>(p)->foo();
}
template<class T>
static auto foo(char, B*) -> typename std::enable_if<not hasFoo<T>::value, int>::type {
std::cout << "B::foo" << std::endl;
return 42;
}
};
struct A: B<A> { };
struct C: B<C> {
int foo() {
std::cout << "C::foo" << std::endl;
return 0;
}
};
int main() {
A a;
a.foo();
std::cout << "---" << std::endl;
B<A> *ba = new A;
ba->foo();
std::cout << "---" << std::endl;
C c;
c.foo();
std::cout << "---" << std::endl;
B<C> *bc = new C;
bc->foo();
}
If I did it right, there are no virtual methods, but the right implementation of foo is called, no matter if you are using a base class or a derived one.
Of course, it is designed around the CRTP idiom.
I know, the member detector class is far from being good.
Anyway, it's enough for the purpose of the question, so...
I believe, I understand what you are trying to do. If I am correct in my understanding, that can't be done.
Logically, you would want to have mult in Base to check if mult is present in the child struct - and if it does, call it, if it does not, provide some default implementation. The flaw here is that there always be mult in child class - because it will inherit implementation of checking mult from Base. Unavoidably.
The solution is to name function differently in the child class, and in the base check for presence of differently named function - and call it. This is a simple thing to do, let me know if you'd like the example. But of course, you will loose the beauty of override here.