Consider my simple example below:
#include <iostream>
template <typename T>
class Base
{
public:
static constexpr int y = T::x;
};
class Derived : public Base<Derived>
{
public:
static constexpr int x = 5;
};
int main()
{
std::cout << Derived::y << std::endl;
}
In g++, this compiles fine and prints 5 as expected. In Clang, however, it fails to compile with the error no member named 'x' in 'Derived'. As far as I can tell this is correct code. Is there something wrong with what I am doing, and if not, is there a way to have this work in Clang?
As linked in the comments, Initializing a static constexpr data member of the base class by using a static constexpr data member of the derived class suggests that clang behaviour is standard conformant up to C++14 here. Starting with Clang 3.9, your code compiles successfully with -std=c++1z.
An easy possible workaround is to use constexpr functions instead of values:
#include <iostream>
template <typename T>
class Base
{
public:
static constexpr int y() {return T::x();}
};
class Derived : public Base<Derived>
{
public:
static constexpr int x() {return 5;}
};
int main()
{
std::cout << Derived::y() << std::endl;
}
This probably isn't the answer anyone would be looking for, but I solved the problem by adding a third class:
#include <iostream>
template <typename T>
class Base
{
public:
static constexpr int y = T::x;
};
class Data
{
public:
static constexpr int x = 5;
};
class Derived : public Base<Data>, public Data {};
int main()
{
std::cout << Derived::y << std::endl;
}
It works as desired, but unfortunately it doesn't really have the benefits of CRTP!
Related
I have two interfaces that I want to use with CRTP for static polymorphism. One of them contains a function whose types in the signature are implementation-dependent.
This problem looks like what has been asked here without solution. The solution I came up with includes an additional templated structure defining the type. This template is then specialized for the implementation avoiding the "invalid use of incomplete type" error.
Here my code
#include <iostream>
#include <memory>
template<class impl1>
struct Interface1 {
double foo() { return static_cast<impl1*>(this)->fooimpl();}
};
template<class impl1, class impl2>
struct typeHelp;
template<class impl1, class impl2>
struct Interface2 {
void bar(typename typeHelp<impl1,impl2>::type value) {
static_cast<impl2*>(this)->barimpl(value);
}
};
//Implementation2 pre declaration
template<class impl1>
struct Implementation2;
//Partial specialization of templated typeHelp
template<class impl1>
struct typeHelp<impl1, Implementation2<impl1>> {
using type = int;
};
//Implementation2
template<class impl1>
struct Implementation2 : public Interface2<impl1, Implementation2<impl1>> {
std::shared_ptr<Interface1<impl1>> imp1;
void barimpl(typename typeHelp<impl1,Implementation2>::type value) {
std::cout << imp1->foo() << " " << value << std::endl;
}
};
//Implementation1
struct Implementation1 : public Interface1<Implementation1> {
double fooimpl() {return 0.;}
};
int main()
{
Implementation2<Implementation1> obj;
obj.imp1 = std::make_shared<Implementation1>();
obj.bar(4);
}
What I don't like in this code is that Interface2 and typeHelp depend on template parameter impl1. This works for my particular case, where Implementation2 is templated with respect to impl1 but it wouldn't if Implementation2 weren't. I wonder if there is a more general and elegant solution to this problem.
My bad; a little bit more of search and I would have found the answer. On this link, Andy G points out that it is possible to specialize a class template with a templated class. The result is more clean than before
#include <iostream>
#include <memory>
//Interface1.hpp
template<class impl1>
struct Interface1 {
double foo() { return static_cast<impl1*>(this)->fooimpl();}
};
//Interface2.hpp
template<class impl2>
struct typeHelp;
template<class impl2>
struct Interface2 {
void bar(typename typeHelp<impl2>::type value) {
static_cast<impl2*>(this)->barimpl(value);
}
};
//Implementation2.hpp
template<class impl1>
struct Implementation2;
//specialization of typeHelp with templated class
template<class impl1>
struct typeHelp<Implementation2<impl1>> {
using type = int;
};
//Actual implementation of Implementation2
template<class impl1>
struct Implementation2 : public Interface2<Implementation2<impl1>> {
std::shared_ptr<Interface1<impl1>> imp1;
void barimpl(typename typeHelp<Implementation2<impl1>>::type value) {
std::cout << imp1->foo() << " " << value << std::endl;
}
};
//Implementation1.hpp
struct Implementation1 : public Interface1<Implementation1> {
double fooimpl() {return 0.;}
};
//Main.hpp
int main()
{
Implementation2<Implementation1> obj;
obj.imp1 = std::make_shared<Implementation1>();
obj.bar(4);
}
I want to find out what is the parent of the type class T in a template function, suppose I've the following classes:
class A{
...
}
class B: public A{
...
}
class C: public B{
...
}
template<typename T>
size_t getBaseHashCode()
{
return typeid(base_of(T)).hashcode();
}
int main()
{
A a;
C c;
size_t size = getBaseHashCode<C>();// must return hashcode of class B
}
is there anyway to find parent of type T and implement base_of function?
Edit:
indeed what I want to do is:
I've factory class which creates objects for me:
template <typename B>
class Factory{
public:
template <typename D>
void registerType(std::string name)
{
static_assert(std::is_base_of<B, D>::value, "class doesn't derive from the base");
table_[name] = &createFunc<D>;
}
B* create(std::string name)
{
const auto it = table_.find(name);
if(it != table_.end())
return it->second();
FILE_LOG(logERROR) << "unidentified option, acceptable options are:";
for(auto const &m : list())
FILE_LOG(logERROR) << '\t' << m;
return nullptr;
}
std::vector<std::string> list()
{
std::vector<std::string> lst;
for(auto const &iter : table_)
lst.push_back(iter.first);
return lst;
}
private:
template<typename D>
static B* createFunc()
{
return new D();
}
typedef B* (*PCreateFunc)();
std::map<std::string, PCreateFunc> table_;
};
in the registerType function I want to set some properties of type D or it's parent and then in the create function, I want to create objects based on that.
You might also consider using some parent wrappers to automatize typedefing:
#include <type_traits>
#include <typeinfo>
#include <iostream>
template <class P>
struct base: P {
using base_type = P;
};
struct A{ };
struct B: base<A>{ };
struct C: base<B>{ };
template <class T>
auto base_of(T) -> typename T::base_type;
template <class T>
using base_of_t = decltype(base_of(std::declval<T>()));
int main() {
std::cout << typeid(base_of_t<C>).name() << std::endl;
}
Output:
1B
Output of c++filt -t 1B:
B
[live demo]
Note it still does not deal with multiple inheritance
You can use a couple of functions declarations that you don't have to define.
It follows a minimal, working example:
#include<utility>
#include<typeinfo>
#include<iostream>
class A{};
class B: public A{};
class C: public B{};
B base_of(const C &);
A base_of(const B &);
template<typename T>
void getBaseHashCode() {
std::cout << typeid(decltype(base_of(std::declval<T>()))).name() << std::endl;
}
int main() {
getBaseHashCode<B>();
getBaseHashCode<C>();
}
It exploits the fact that, in this case, you have exact matches during the invokations. It's quite weak a solution, but works with the example code in the question.
That said, I agree on the fact that the whole question looks like an XY-problem.
EDIT
As mentioned by #Jarod42 in the comments, a more idiomatic (and verbose) way would be by using traits.
It follows a minimal, working example:
#include<typeinfo>
#include<iostream>
class A{};
class B: public A{};
class C: public B{};
template<typename> struct base_of;
template<> struct base_of<B> { using type = A; };
template<> struct base_of<C> { using type = B; };
template<typename T>
void getBaseHashCode() {
std::cout << typeid(typename base_of<T>::type).name() << std::endl;
}
int main() {
getBaseHashCode<B>();
getBaseHashCode<C>();
}
This will solve also the problem due to multiple inheritance. The designer of base_of specializations will be in charge to promote one of the base classes to the role of preferred one.
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.
Two methods for accessing template base class members are described here. When the base class member itself is a template, accessing it using the first method (this->) above is described here. Is there a way to use the second method (using xxxx) in this scenario as well?
For example, in the code below, is it possible to replace "????" with something to make the code work?
using namespace std;
template<typename T> class base
{
public:
template<bool good> void foo()
{
cout << "base::foo<" << boolalpha << good << ">()" << endl;
}
};
template<typename T> class derived : public base<T>
{
public:
using ????
void bar()
{
foo<true>();
}
};
Just for the record, even though it does not provide any answer or workaround, but I am currently working with VS Express 2013, and I can assure you that
#include <iostream>
template<typename T> class base
{
public:
template<bool good> void foo()
{
std::cout << "base::foo<" << good << ">()" << std::endl;
}
};
template<typename T> class derived : public base<T>
{
public:
void bar()
{
foo<true>();
}
};
struct A{};
void main() {
derived<A> a;
a.bar();
}
works perfectly fine...
I have defined below hierarchy of classes, my intention is to design a generic class that allows me to iterate over enum objects (C++11 is not allowed to be used unfortunately). The class definition and test program are:
// base.h
#include <set>
template <typename T>
class Base
{
protected:
explicit Base(int value);
typedef typename std::set< Base<T>* > instances;
static instances s_instances;
int value_;
public:
int get_value() const { return value_ ; }
};
template <typename T>
Base<T>::Base(int value): value_(value)
{
s_instances.insert(this);
}
// derived.h
#include "base.h"
class Derived : public Base<Derived>
{
protected:
explicit Derived(int value): Base<Derived>(value) { }
public:
static const Derived value1;
};
// test.cc
#include "derived.h"
template<>
Base<Derived>::instances Base<Derived>::s_instances;
const Derived Derived::value1(1);
int main(int argc, char *argv[])
{
using std::cout;
using std::endl;
cout << Derived::value1.get_value() << endl;
}
On compilation using g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, it gives me below linking error:
"
g++ test.cc -o test
/tmp/ccOdkcya.o: In function `Base<Derived>::Base(int)':
test.cc:(.text._ZN4BaseI7DerivedEC2Ei[_ZN4BaseI7DerivedEC5Ei]+0x28): undefined reference to `Base<Derived>::s_instances'
collect2: ld returned 1 exit status
"
Can anyone please suggest what am I missing in above code?
Thanks!
Static data members are declared in class definitions and defined outside the class definition. Like this:
// header:
class C {
static int i;
};
// source:
int C::i = 17;
With a template, you typically don't put any code in source files, so the definition goes in the header:
// header:
template <class T>
class C {
static int i;
};
template <class T>
int C<T>::i = 17;
Be aware that s_instances might not have been initialized before it is used.
You can only write
// template<> -> you should not write this in this case.
Base<Derived>::instances Base<Derived>::s_instances;
If you have provided an explicit specialization of Base<Derived>, such as :
class Derived;
template <>
class Base<Derived>
{
protected:
explicit Base(int value);
typedef typename std::set< Base<Derived>* > instances;
static instances s_instances;
int value_;
public:
int get_value() const { return value_ ; }
};
Otherwise, you have to stick to writing:
template<typename T>
typename Base<T>::instances Base<T>::s_instances;