Autodesk / Autodesk/AutomaticComponentToolkit
Add template classes
- Dominant language
- Go
- Stars
- 53
- Forks
- 26
- PR merge metrics
- No merged PRs in 30d
Description
Currently ACT does not support generic classes (aka template classes) which makes it hard to define certain types such as (type-safe) generic containers and algorithms.
For example, to define types like `Map`, `Map`, and `Map` in the API today, you would need to define the following:
```xml
```
This quickly becomes unmaintainable as for N instantiations you need to:
* Copy-paste and adjust the method definitions N times
* Maintain N implementation classes by:
* Writing the same code N times, or
* Writing a generic `Map` class yourself and inheriting from that N times (something like `class StringBarMap : public Map`)
Instead, ACT could provide support for generic classes, and it could look something like this (following previous discussions with @martinweismann and @alexanderoster):
```xml
```
The implementation stubs could then be generated as follows:
```c++
// Implementation Stubs
namespace Component { namespace Impl {
template
class CMap
{
public:
virtual void Add(TKey Key, TValue Value);
virtual TValue Get(TKey Key);
virtual void GetOut(TKey Key, TValue *pValue);
virtual void Clear();
virtual Component_uint32 Count();
};
class IntFooMap : public CMap
{
/* instantiates to:
virtual void Add(Component_int32 Key, IFoo * Value);
virtual IFoo * Get(Component_int32 Key);
virtual void GetOut(Component_int32 Key, IFoo **pValue);
virtual void Clear();
virtual Component_uint32 Count();
*/
};
class StringBarMap : public CMap
{
/* instantiates to:
virtual void Add(String * Key, IBar * Value);
virtual IBar * Get(String * Key);
virtual void GetOut(String * Key, IBar **pValue);
virtual void Clear();
virtual Component_uint32 Count();
*/
};
class IntDoubleMap : public CMap
{
/* instantiates to:
virtual void Add(Component_int32 Key, double Value);
virtual double Get(Component_int32 Key);
virtual void GetOut(Component_int32 Key, double *pValue);
virtual void Clear();
virtual Component_uint32 Count();
*/
};
}} // namespace Component::Impl
```
And the bindings:
```c++
// Bindings
namespace Component { namespace Binding {
class CMap
{
public:
virtual void Clear();
virtual Component_uint32 Count();
};
class IntFooMap : public CMap
{
virtual void Add(Component_int32 Key, IFoo * Value);
virtual IFoo * Get(Component_int32 Key);
virtual void GetOut(Component_int32 Key, IFoo **pValue);
};
class StringBarMap : public CMap
{
virtual void Add(String * Key, IBar * Value);
virtual IBar * Get(String * Key);
virtual void GetOut(String * Key, IBar **pValue);
};
class IntDoubleMap : public CMap
{
virtual void Add(Component_int32 Key, double Value);
virtual double Get(Component_int32 Key);
virtual void GetOut(Component_int32 Key, double *pValue);
};
}} // namespace Component::Binding
```
The API author would then only need to implement the template class CMap once.
Notes:
* Only works with strings if they're wrapped in a class
* Already a need for string wrapper class
* Can't support string without wrapper class because of different in/out/return types (`const std::string&` / `std::string &` / `std::string`)
* Template class signatures would differ from the simple / class types, won't work.
* Ref counting, need to check if type is a pointer or not to decide whether or not to call IncRefCount/DecRefCount.
* Provide a helper function with specializations for class / simple types
* Concepts
* Example: key type for map, how to compare?
* `pLhs->Compare(pRhs)`?
* `pLhs < pRhs`?
* Leave it up to the API author, C++ (pre C++20) didn't have support for Concepts either and relied on documentation
* API author can choose to write template functions with specializations like (ACT could document an example)
```c++
template
struct compare_helper {
static int compare(T lhs, T rhs);
};
template
struct compare_helper>>> {
static int compare(Comparable pLhs, Comparable pRhs) {
static_assert(std::is_member_function_pointer::Compare)>::value,
"Type does not implement Comparable concept (Comparable::Compare is not a member function).");
return pLhs->Compare(pRhs);
}
};
template
struct compare_helper>> {
static int compare(Comparable lhs, Comparable rhs) {
return lhs - rhs;
}
};
template
int compare(T lhs, T rhs) {
return compare_helper::compare(lhs,rhs);
}
// compare(pObject1, pObject2) => compiles only if pObject1 has Compare method
// compare(1,2)
```
Contributor guide
Assessment
This issue has not been assessed yet.