Why does conceptual class template specialization cause an error - template-specialization

I tried to build the following with gcc 10 -std=gnu++20 -fconcepts:
template <std::signed_integral T>
class MyClass{ T a; };
template <std::unsigned_integral T>
class MyClass{ T a; };
Why does this code cause the following error?
> declaration of template parameter ‘class T’ with different constraints
> 55 | template <std::unsigned_integral T>
> | ^~~
Shouldn't it be fine?

Shouldn't it be fine?
No, constraints don't make classes "overloadable". You still need a primary template and then you need to specialize that template:
template <std::integral T>
class MyClass;
template <std::signed_integral T>
class MyClass<T>{ T a; };
template <std::unsigned_integral T>
class MyClass<T>{ T a; };

Related

Vala: calling super class creation method at constructor

I have been trying to initialize a parent class using it's creation method.
class A {
public A.creator (int x, int y) {
// do some magic
}
}
class B : A {
public B.creator (int x, int y) {
// I want to do something like
base.creator (x, y);
}
}
I am facing an error while trying to run the above code.
error: chain up to 'A.creator' not supported
What's the correct way to accomplish this in vala?
When I try to compile your code I get:
chain.vala:1.1-1.7: error: Class name `A' is too short
class A {
^^^^^^^
chain.vala:7.1-7.11: error: Class name `B' is too short
class B : A {
^^^^^^^^^^^
Compilation failed: 2 error(s), 0 warning(s)
After renaming A to Aaa and B to Bbb the code compiles just fine with valac 0.36.15.
My first thought was that you might have to derive A from Object, but apparently that is not the case.

CLANG: Elaborated type refers to a typedef error

Here is my code snippet
template <class T>
struct ClassFriendMaker
{
typedef T Type;
};
template <class T>
class Singleton
{
friend class ClassFriendMaker<T>::Type; // Problem in this line
//Other declaration
}
When compiled with CLANG, it gave me an error:
error: elaborated type refers to a typedef
friend class ClassFriendMaker<T>::Type;
^
May I know what's wrong ? Thankyou
Replace class with typename in friend declaration
friend class ClassFriendMaker<T>::Type;
friend typename ClassFriendMaker<T>::Type;

iOS how to wrapper C++ class in Swift project

I have a static library in C++, and now I want to use this library in my new Swift project. I found that I couldn't use C++ class directly in Swift project, so I have to wrapper this library in OC. Then I have some problem wrapping this:
//AbstractClassA.h
#include <string>
class AbstractClassA {
public:
virtual string getString() = 0;
virtual int getInt() = 0;
virtual ~AbstractClassA() {};
};
//AbstractClassB.h
class AbstractClassB {
public:
virtual void function(int a) = 0;
virtual ~AbstractClassB() {};
};
//ChildA.h
#include "AbstractClassA.h"
#include "AbstractClassB.h"
class ChildA : public AbstractClassA
{
public:
ChildA(int a = 640);
ChildA( AbstractClassB* classb, int a = 640);
virtual ~ChildA();
string getString();
int getInt();
protected:
int a;
string b;
};
How to wrapper these classes in OC? Thanks for any help!
You create an Objective-C++ class that wraps the C++ class. The header file must not contain any C++ features; the file with the implementation must end in .mm to tell Xcode to use the Objective-C++ compiler, not Objective-C.
In the .h file, you'd have an interface for class ChildAWrapper, methods init, initWithInt:, initWithClassB:, initWithClassB:Int: and readonly properties stringValue and intValue.
In the .mm file, you'd have an instance variable of type ChildA*. The init methods create a ChildA object. dealloc deletes it. You implement the properties by calling the methods of the ChildA object, converting the std::string to an NSString*.
Same for ClassB with an Objective-C class ClassBWrapper. There you want a readonly property void* wrappedClass returning a pointer to the the ClassB object, converted to void*, because ChildAWrapper will need that.

Mocking C++ classes with dependency injection

Say you're testing class A and it has a dependency injection of B which has a dependency injection of C.So you mock B but the only constructor it has requires an injection of C, so do you have to mock C as well and inject the mocked C into the mocked B and only then inject it to A?What if you have 5 consecutive dependancies?
What are the alternatives?
I use Google Mock, so a specific answer would help as well.
Emile has the right idea, you should depend on interfaces not concrete classes. So in your example it would be something like:
#include <iostream>
using namespace std;
class C {
public:
int x;
};
class B {
public:
~B(){};
virtual void doSomething() = 0;
};
class ConcreteB : public B{
public:
ConcreteB(C c) : m_c(c) {}
void doSomething(){
std::cout << "HelloWorld" << std::endl;
}
private:
C m_c;
};
class A{
public:
A(B *b): m_b(b){}
void functionToTestWithSideEffect(){
m_b->doSomething();
}
private:
B *m_b;
};
//#include <gmock/gmock.h>
int main() {
C c;
c.x = 42;
ConcreteB b(c);
A a(&b);
a.functionToTestWithSideEffect();
return 0;
}
In your tests you create a mock B which does not rely on any class C. Then you are only testing the interface with B. In this way you break A's dependency on C. Creating a mock B that doesn't depend on C is pretty simple:
class MockB : public B {
public:
MOCK_METHOD0(doSomething, void());
};
If you change the design so that the classes depend on interfaces instead of concrete classes, you get rid of the constructor problems. Besides improving testability, it may also improve reusability and maintainability, at the cost of more code (interfaces).
In this case you should inject by pointer and not by reference, then you could pass a NULL pointer. This would work assuming you're object is indeed a mock and not a fake object, therefore it has no real dependency on the injected object.
For boost::shared_ptr you could do the following:
boost::shared_ptr<C> null_c_ptr;
MockB mock_b(null_c_ptr);

Do C++ Templates play nicely with VCL classes?

I'm trying to use C++ Template 'mixins' to create some new VCL components with shared additional functionality. Example...
template <class T> class Mixin : public T
{
private:
typedef T inherited;
// ...additional methods
public:
Mixin(TComponent *owner) : inherited(owner)
{
// .. do stuff here
};
};
Used like this:
class MyLabel : public Mixin<TLabel>
{
....
}
class MyEdit : public Mixin<TEdit>
{
....
}
Now, everything compiles fine, and the mixin stuff seems to work - until I try and save the component to a stream using TStream->WriteComponent, where the inherited properties (eg TLabel.Width/Height/etc.) don't get written. This is even with a 'null' mixin like the one shown above.
My code works fine when just deriving classes directly from TForm, TEdit, etc - and the class is correctly registered with the streaming system.
The quick/simple answer is: no; when dealing with a template, the compiler won't generate the proper descriptors to make streaming working. However, since this has come up before, I peeked under the cover to find out what's missing. And what I found is that it's almost there. So here's a little more information.
Upfront the compiler will never treat a template-based type as a Delphi. For example, do something like this:
void testing()
{
__classid(Mixin<Stdctrls::TLabel>); // Error Here
}
... and you'll see the error
"Error E2242 test.cpp 53: __classid requires Delphi style class type (i.e. class marked __declspec(delphiclass) or derived from System::TObject) in function testing()"
This basically says the compiler does not consider this type/class as compatible with Delphi-classes [i.e. those that derive from TObject]. Internally there's just a flag on the symbol that says whether the type is delphi-compatible or not. And I noticed that I could trick the compiler into marking the type as delphi-style if I forced it to walk up the hierarchy.. which is something it has to do if I create an instance of the object. So, with this hack the error goes away:
void testing()
{
typedef Mixin<Stdctrls::TLabel> __ttype;
std::auto_ptr<__ttype> c2(new __ttype(0));
__classid(Mixin<Stdctrls::TLabel>); // No more errors here
}
But much nicer was actually to use the __declspec(delphiclass) directly on the template, as in:
template <class T>
class __declspec(delphiclass) Mixin : public T {
private:
int i;
typedef T inherited;
public:
__fastcall Mixin(TComponent *owner) : inherited(owner) {};
};
So now that the compiler treats the type as a delphi-style class without hacks, I peeked a little more and found the issue you're probably running into: Delphi classes have the TTypeData.PropCount field - http://docwiki.embarcadero.com/VCL/en/TypInfo.TTypeData - which is a sum of the class' properties, including those of its base classes. Due to the way the various pieces of information are computed, the compiler writes out a '0' for that field when a template is involved:(
You can see this by printing out the PropCount, as in:
#include <Stdctrls.hpp>
#include <cstdio>
#include <memory>
#include <utilcls.h>
class TCppComp : public Classes::TComponent {
int i;
public:
__fastcall TCppComp(TComponent* owner): Classes::TComponent(owner) {};
__published:
__property int AAAA = {read=i, write=i};
};
template <class T>
class __declspec(delphiclass) Mixin : public T {
private:
int i;
typedef T inherited;
public:
__fastcall Mixin(TComponent *owner) : inherited(owner) {};
};
typedef Mixin<TCppComp> TMixinComp;
void showProps(TClass meta) {
PTypeInfo pInfo = PTypeInfo(meta->ClassInfo());
int Count = GetPropList(pInfo, tkAny, NULL);
TAPtr<PPropInfo> List(new PPropInfo[Count]);
std::printf("Class: %s - Total Props:%d\n",
AnsiString(pInfo->Name).c_str(), Count);
GetPropList(pInfo, tkAny, *(reinterpret_cast<PPropList*>(&List)));
for (int i = 0; i < Count; i++) {
AnsiString propName(List[i]->Name);
std::printf("\t%s\n", propName.c_str());
}
}
void test() {
showProps(__classid(TCppComp));
showProps(__classid(TMixinComp));
}
int main() {
test();
return 0;
}
When run the above prints:
Class: TCppComp - Total Props:3
AAAA
Name
Tag
Class: #%Mixin$8TCppComp% - Total Props:0
IOW, Mixin shows up with '0' published properties while its base type has 3:(
I suspect the streaming system relies on this count and that's why inherited properties are not being written out in your setup.
I considered tweaking the generated descriptors at runtime but since we write them to _TEXT it's bound to trigger DEP.
I'll look at the logic that computes the PropCount to see if there's some way to get it to compute the correct number. If time allows, please do open a QC for this: now that I've peek underneath, I believe it would not require much effort to get this working as expected.
Cheers,
Bruneau
PS: In my sample I even had the Mixin publish a property and the compiler generated the correct descriptor for that property; however, the total count was still zero.

Resources