The below code compiles in g++ but error out in clang++. How to fix this code so that it can compile in both?
class A {
private:
template<int _N> class B {
public:
static constexpr int N = _N;
};
class C {
public:
template <typename B>
B* func();
};
};
template <typename B>
B* A::C::func()
{
constexpr int N = B::N;
}
clang prior clang 11 is unbale to resolve the name B properly. The solution is use another template parameter name:
template <typename D>
D* A::C::func()
{
constexpr int N = D::N;
}
The full example requires the public access to A::C at least or a friend function.
class A {
private:
template<int N_> class B {
public:
static constexpr int N = N_;
};
class C {
public:
template <typename B>
B* func();
};
friend int main();
};
template <typename D>
D* A::C::func() {
constexpr int N = D::N;
return nullptr;
}
int main() {
A::C c;
auto *n = c.func<A::B<0>>();
}
Related
I'm trying to do this:
struct A
{
typedef void NoHalf;
};
struct B : A
{
typedef A Half;
};
struct C : B
{
typedef B Half;
};
template<class T, typename = T::NoHalf> void TEST() { };
template<class T, typename = T::Half> void TEST()
{
TEST<T::Half>();
};
int main()
{
TEST<A>();
TEST<B>();
TEST<C>();
};
So the TEST<C> function should do something with class C, then recurse TEST<B>, then to TEST<A> and stop there. Unfortunately I get bunch of errors like TEST has already been defined and funny enough also TEST identifier not found. What am I doing wrong and how to fix that?
Ok, so here's a solution, quite uglier, but seems working:
struct A
{
typedef void Half;
static const int I = 0;
};
struct B : A
{
typedef A Half;
static const int I = 1;
};
struct C : B
{
typedef B Half;
static const int I = 2;
};
template<class T> std::enable_if_t<std::is_void_v<T> > TEST() { };
template<class T> std::enable_if_t<!std::is_void_v<T> > TEST()
{
printf("%i", T::I);
TEST<T::Half>();
};
int main()
{
TEST<A>();
TEST<B>();
TEST<C>();
};
I have a the following class template
template<int N>
constexpr int arraySize() { return arraySize<N-1>() + N; }
template<>
constexpr int arraySize<0>() { return 0; }
template<int C>
class MyClass {
public:
std::array<int, arraySize<C>()> arr;
};
int main() {
MyClass<3> cls;
std::cout << cls.arr.size() << std::endl; // Output: 6
}
Everything works but I would like to have calculateArraySize<N>() as a member function. I've tried the following:
template<int C>
class MyClass {
public:
static constexpr int arraySize();
std::array<int, MyClass<C>::arraySize()> arr;
};
template<int C>
constexpr int MyClass<C>::arraySize(){ return MyClass<C-1>::arraySize() + C; }
template<>
constexpr int MyClass<0>::arraySize() { return 0; }
Results in the following error:
fatal error: recursive template instantiation exceeded maximum
depth of 1024
std::array::arraySize()> arr;
template<int C>
class MyClass {
public:
template<int N>
static constexpr int arraySize();
std::array<int, MyClass::arraySize<C>()> arr;
};
template<int C>
template<int N>
constexpr int MyClass<C>::arraySize(){ return MyClass::arraySize<N-1>() + N-1; }
template<int C>
template<>
constexpr int MyClass<C>::arraySize<0>() { return 0; }
Gives the following error:
tmp.cc:19:27: error: cannot specialize (with 'template<>') a member of an
unspecialized template
constexpr int MyClass::arraySize<0>() { return 0; }
Is it possible to achieve the desired behaviour? Solutions using C++14/C++17 features (I guess it should be possible usinn if-constexpr) are welcomed but won't solve my particular problem since only C++11 is available.
You can move the function into the class and the specialize the entire class for the base case. That looks like:
template<int C>
class MyClass {
public:
static constexpr int arraySize(){ return MyClass<C-1>::arraySize() + C; }
std::array<int, MyClass<C>::arraySize()> arr;
};
template<>
class MyClass<0> {
public:
static constexpr int arraySize(){ return 0; }
};
int main() {
MyClass<3> cls;
std::cout << cls.arr.size() << std::endl; // Output: 6
}
Live Example
You can also use a member variable instead of a member function.
template <int C>
class MyClass {
public:
static constexpr int array_size = MyClass<C-1>::array_size + C;
std::array<int, array_size> arr;
};
template <>
class MyClass<0> {
public:
static constexpr int array_size = 0;
};
In my project I played with the following design :
enum {
A = 1, B = 2, C = 4
};
struct Foo { int foo; };
template <int> struct Bar;
template <> struct Bar<A> : public virtual Foo { int a; };
template <> struct Bar<B> : public virtual Foo { int b; };
template <> struct Bar<C> : public virtual Foo { int c; };
Now I can do something fun like :
template <> struct Bar<A|B> : public A, public B {};
template <> struct Bar<A|C> : public A, public C {};
template <> struct Bar<B|C> : public B, public C {};
template <> struct Bar<A|B|C> : public A, public B, public C {};
So that I can write :
Bar<A|C> bar;
bar.foo = 2;
bar.a = 1;
bar.c = 2;
Now I would like the generation of the combination classes Bar<X|Y|Z|..> to be automatically done when the user creates such an instance.
Is this possible using some template magic ?
Something along the lines of :
template <int N, class ...Classes> struct Bar<N> : public Classes... {};
template <int N> struct Bar<N> : public Bar<N, generate_classes<N> > {};
where generate_classes would be able to generate the list of classes Bar<N> should inherit from.
No need in fancy schmancy SFINAE, parameter packs or any such dark wizardry.
enum {
A = 1, B = 2, C = 4
};
struct Foo { int foo; };
template <unsigned int> struct Bar; // unsigned because bit fiddling
template <> struct Bar<A> : public virtual Foo { int a; };
template <> struct Bar<B> : public virtual Foo { int b; };
template <> struct Bar<C> : public virtual Foo { int c; };
template <unsigned int i> struct Bar :
public Bar<i & ~(i-1)>, // only least significant set bit
public Bar<i & (i-1)> // all other set bits
{ };
// checking
int main ()
{
Bar<A|B|C> abc;
abc.a = 0; // ok
abc.b = 0; // ok
abc.c = 0; // ok
Bar<A|B> ab;
ab.a = 0; // ok
ab.b = 0; // ok
ab.c = 0; // error
Bar<A|C> ac;
ac.a = 0; // ok
ac.b = 0; // error
ac.c = 0; // ok
Bar<9> x; // error
}
Instead of thinking about somehow generating a list of classes to be inherited you can think of it as choosing them. This one should be inherited, this one shouldn't. This can be achieved by static dispatching through template parameter. So we get a template that based on a bool parameter gives either T or an empty class. It is likely to be optimized (it may even be guaranteed in this case, but I'm not sure what exact requirements given by the standard are) by empty base optimization so there is no memory overhead.
#include <iostream>
enum {
A = 1, B = 2, C = 4
};
template <class T, bool Enable>
struct or_empty;
template <class T>
struct or_empty<T, false>
{
struct empty {};
using type = empty;
};
template <class T>
struct or_empty<T, true>
{
using type = T;
};
template <class T, bool Enable>
using or_empty_t = typename or_empty<T, Enable>::type;
struct Foo { int foo; };
template <int I> struct Bar :
public or_empty_t<Bar<A>, I&A>,
public or_empty_t<Bar<B>, I&B>,
public or_empty_t<Bar<C>, I&C> {};
template <> struct Bar<A> : public virtual Foo { int a; };
template <> struct Bar<B> : public virtual Foo { int b; };
template <> struct Bar<C> : public virtual Foo { int c; };
int main()
{
Bar<A|C> bar;
bar.foo = 2;
bar.a = 1;
// bar.b = 2; error
bar.c = 2;
std::cout << bar.foo << ' ' << bar.a << ' ' << bar.c << '\n';
std::cout << sizeof(Bar<A>) << ' ' << sizeof(Bar<A|B>) << ' ' << sizeof(Bar<A|B|C>) << '\n';
}
Demo: http://coliru.stacked-crooked.com/a/f170fbd873739c38
Some machinery to do compile-time unpacking of flags:
enum flag_e { None = 0, A = 1, B = 1<<1, C = 1<<2 };
template<flag_e...>
struct flags {using type=flags; constexpr flags(){}};
template<flag_e>
struct flag{using type=flag; constexpr flag(){}};
constexpr flags<A,B,C> all_flags{};
template<flag_e...lhs, flag_e...rhs>
constexpr flags<lhs...,rhs...> operator+(flags<lhs...>, flags<rhs...>)
{ return {}; }
template<flag_e lhs, flag_e...rhs>
inline constexpr flags<lhs, rhs...> operator+(flag<lhs>, flags<rhs...>)
{ return {}; }
template<flag_e...lhs, flag_e rhs>
inline constexpr flags<lhs..., rhs> operator+(flags<lhs...>, flag<rhs>)
{ return {}; }
template<flag_e...fs>
inline constexpr flags<fs...> operator+(flag<None>, flags<fs...>)
{ return {}; }
template<flag_e...fs>
inline constexpr flags<fs...> operator+(flags<fs...>, flag<None>)
{ return {}; }
template<flag_e f, flag_e...fs>
inline constexpr auto unpack( flag<f>, flags<fs...> x, flags<> )
-> flags<fs...>
{ return {}; }
template<flag_e f, flag_e...fs, flag_e c0, flag_e...checks>
inline constexpr auto unpack( flag<f> fin, flags<fs...> x, flags<c0, checks...> )
-> decltype( unpack( fin, x+flag<flag_e(f&c0)>{}, flags<checks...>{} ) )
{ return {}; }
template<flag_e f>
inline constexpr auto unpack( flag<f> fin )
-> decltype( unpack( flag<f>{}, flags<>{}, all_flags ) )
{ return {}; }
Then we use it:
template <int> struct Bar;
template <class flags> struct BarImpl;
template <flag_e...fs> struct BarImpl<flags<fs...>>:
Bar<fs>...
{};
template <int flags> struct Bar:
BarImpl<decltype(unpack(flag<flag_e(flags)>{}))>
{};
struct Foo { int foo; };
template <> struct Bar<A> : public virtual Foo { int a; };
template <> struct Bar<B> : public virtual Foo { int b; };
template <> struct Bar<C> : public virtual Foo { int c; };
Live example.
The code that lets you have bundles of flags and individual flags can be made more generic at the cost of mentioning the flag_e type more often.
I made it overly slick, with the ability to say flags<A>+flags<B> and get flags<A,B>, because I like that notation.
I then wrote unpack, which takes flag<A|B> and produces flags<A,B>.
In C++14 and 17 things get slicker, which folds and return type deduction and the like.
I wonder whether the below tricky situation is possible:
Suppose I have a template class template <typename DTYPE> class A{};, where DTYPE is supposed to be one of uint8_t, uint16_t, etc. I want to add a friend class to A, but this friend class differs for each DTYPE alternative. Further, suppose the friend classes for different DTYPE values are not instantiations of another template class, but independent classes.
Is there a way to do it?
You can add template "proxy" class FriendOfA and specialize it for whatever type you need:
// actual friends
class FriendUint8 {};
class FriendUint16 {};
template<typename T> struct FriendOfA;
template<>
struct FriendOfA<uint8_t> {
typedef FriendUint8 type;
};
template<>
struct FriendOfA<uint16_t> {
typedef FriendUint16 type;
};
// optional helper
template <typename T>
using FriendOfA_t = typename FriendOfA<T>::type;
template<class T>
class A {
friend typename FriendOfA<T>::type;
// or simply
friend FriendOfA_t<T>;
};
I believe you're looking for something like that:
#include <iostream>
struct BaseFriend
{
template <typename T>
void boo(const T& t) { t.foo(); }
};
struct BaseFriendProxy
{
template <typename T>
void boo(const T& t) { std::cout << "Proxy: "; t.foo(); }
};
template <typename TType>
struct Friend ;
template <>
struct Friend<int> {
using T = BaseFriend;
};
template <>
struct Friend<char> {
using T = BaseFriendProxy;
};
template <typename DTYPE>
class A
{
private:
friend typename Friend<DTYPE>::T;
void foo() const
{ std::cout << "A::foo()" << std::endl; }
};
int main()
{
A<int> a;
BaseFriend bf1;
bf1.boo(a);
A<char> b;
BaseFriendProxy bf2;
bf2.boo(b);
return 0;
}
But this will work only with C++11: you can't combine friend class ... with typename X::Y in C++03
Sure you can, specialize your template and add whatever friend class you want:
#include <iostream>
using namespace std;
class base {
public:
virtual int getValue() = 0;
};
class friend1 {
public:
base* ptr;
int getValue() {
return ptr->getValue();
}
};
class friend2 {
public:
base* ptr;
int getValue() {
return ptr->getValue();
}
};
template <typename DTYPE> class A : public base{
public:
A() { data = 42; }
// No friends
private:
int data;
int getValue() {
return data;
}
};
template <> class A<char> : public base{
public:
A() { data = 44; }
friend class friend1;
private:
int data;
int getValue() {
return data;
}
};
template <> class A<bool> : public base{
public:
A() { data = 45; }
friend class friend2;
private:
int data;
int getValue() {
return data;
}
};
int main()
{
A<char> obj1;
friend1 friend_of_obj1;
friend_of_obj1.ptr = &obj1;
cout << friend_of_obj1.getValue() << endl;
A<bool> obj2;
friend2 friend_of_obj2;
friend_of_obj2.ptr = &obj2;
cout << friend_of_obj2.getValue();
}
http://ideone.com/hM9x0y
Yes, a friend can be based on a template. Such as;
template <typename DTYPE>
struct Friend;
template <class DTYPE>
class A {
friend struct Friend<DTYPE>;
};
For each type DTYPE for the class A you wish to support (different by implementation) you can specialise Friend, such as;
template<>
struct Friend<uint8_t> {
// ...
};
A basic working sample:
#include <cstdint>
using namespace std;
template<typename T>
struct Friend;
template <class T>
class A {
friend struct Friend<T>;
int i = 0;
};
template<>
struct Friend<uint8_t> {
void method() {
A<uint8_t> a;
a.i = 8;
}
};
template<>
struct Friend<uint16_t> {
void method() {
A<uint16_t> a;
//A<uint8_t> b; // fails to compile
a.i = 16;
}
};
int main()
{
A<uint8_t> a;
Friend<uint8_t> f;
f.method();
}
I want to be able to get the size of polymorphic object. At the moment I got this:
struct Base {
virtual std::size_t size() const {
return sizeof(*this);
}
};
struct Derived : Base {
virtual std::size_t size() const {
return sizeof(*this);
}
};
Which is literally copy & paste. I want to do better. Suppose I really hate macros and CRTP seems like the only sensible approach. Let us give it a try:
struct SizedBase {
virtual std::size_t size() const = 0;
};
template <typename Type>
struct Sized : virtual SizedBase {
std::size_t size() const override {
return sizeof(Type);
}
};
struct Base : Sized<Base> {};
struct Derived : Base, Sized<Derived> {};
This looks much better, but sadly is ill-formed: Derived contains two final overriders for size() from Base and from Sized<Derived>. We can solve this by inheriting through Sized:
struct SizedBase {
virtual std::size_t size() const = 0;
};
template <typename Type, typename... SizedBases>
struct Sized : virtual SizedBase, SizedBases... {
std::size_t size() const override {
return sizeof(Type);
}
};
struct Base : Sized<Base> {};
struct Derived : Sized<Derived, Base> {};
This works as intended, however gets somewhat confusing in the event of multiple inheritance and prohibits altering accessibility/virtualness of bases.
So, is there a better way?
Not that anyone should really use this, but...
template <typename>
struct None1 {};
template <typename>
struct None2 {};
template <typename T>
struct PrivateBase { using Tpriv = T; using Tprot = None1<T>; using Tpub = None2<T>; };
template <typename T>
struct ProtectedBase { using Tpriv = None1<T>; using Tprot = T; using Tpub = None2<T>; };
template <typename T>
struct PublicBase { using Tpriv = None1<T>; using Tprot = None2<T>; using Tpub = T; };
template <typename K>
struct TriBase : private K::Tpriv, protected K::Tprot, public K::Tpub {};
template <typename T, typename ... Bases>
struct Sized : private Bases::Tpriv..., protected Bases::Tprot..., public Bases::Tpub...
{
virtual size_t size() { return sizeof(T); }
};
struct Foo : Sized<Foo> {};
struct X{};
struct Y{};
struct Bar : Sized<Bar, PrivateBase<X>, ProtectedBase<Y>, PublicBase<Foo>> {};
int main ()
{
Bar b;
Foo* f = &b;
X* x = &b; // error : private base
Y* y = &b; // error : protected base
}
Virtual inheritance is left as an exercise to the reader.
The order of base classes is not preserved, but you should not depend on it anyway.
Something that is a little bit more production-friendly can be implemented like this (this is a rough sketch):
#include <cstdlib>
#include <typeinfo>
#include <unordered_map>
#include <memory>
#include <iostream>
struct myinfo
{
size_t size;
// any other stuff
};
using TypeInfoRef = std::reference_wrapper<const std::type_info>;
struct Hasher
{
std::size_t operator()(TypeInfoRef code) const
{
return code.get().hash_code();
}
};
struct EqualTo
{
bool operator()(TypeInfoRef lhs, TypeInfoRef rhs) const
{
return lhs.get() == rhs.get();
}
};
static std::unordered_map<TypeInfoRef, myinfo, Hasher, EqualTo> typemap;
template <typename K>
struct typemap_initializer
{
typemap_initializer()
{
typemap[typeid(K)] = myinfo{sizeof(K)};
}
};
struct Base
{
virtual ~Base() {}
size_t size() { return typemap[typeid(*this)].size; }
template<typename K, typename... Arg>
friend K* alloc(Arg...);
private:
void* operator new(size_t sz) { return ::operator new(sz); }
};
template<typename K, typename... Arg>
K* alloc(Arg... arg)
{
static typemap_initializer<K> ti;
return new K(arg...);
}
struct Foo : Base {int a;};
struct Bar : Foo {int b; int c;};
int main ()
{
Foo* f = alloc<Foo>();
Bar* g = alloc<Bar>();
std::cout << f->size() << std::endl;
std::cout << g->size() << std::endl;
}
Of course one gives up the familiar Foo* foo = new Foo syntax, but in the era of ubiquitous std::make_shared<> this is not a big problem.