Forked from
Eclipse Projects / aidge / aidge_core
2349 commits behind the upstream repository.
-
Olivier BICHLER authoredOlivier BICHLER authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
DynamicAttributes.hpp 4.58 KiB
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#ifndef AIDGE_CORE_UTILS_DYNAMICATTRIBUTES_H_
#define AIDGE_CORE_UTILS_DYNAMICATTRIBUTES_H_
#include <map>
#include <vector>
#include <type_traits>
#include <typeinfo>
#include <cassert>
#include <string>
#include "aidge/utils/Any.hpp"
#include "aidge/utils/Attributes.hpp"
namespace Aidge {
///\todo store also a fix-sized code that indicates the type
///\todo managing complex types or excluding non-trivial, non-aggregate types
class DynamicAttributes : public Attributes {
public:
/**
* \brief Returning an Attribute identified by its name
* \tparam T expected Attribute type
* \param name Attribute name
* \details assert if T is not the actual Attribute type or if the Attribute does not
* exist
* \note at() throws if the Attribute does not exist, using find to test for Attribute existance
*/
template<class T> T& getAttr(const std::string& name)
{
return libany::any_cast<T&>(mAttrs.at(name));
}
template<class T> const T& getAttr(const std::string& name) const
{
return libany::any_cast<const T&>(mAttrs.at(name));
}
///\brief Add a new Attribute, identified by its name. If it already exists, asserts.
///\tparam T expected Attribute type
///\param name Attribute name
///\param value Attribute value
template<class T> void addAttr(const std::string& name, T&& value)
{
const auto& res = mAttrs.emplace(std::make_pair(name, libany::any(std::forward<T>(value))));
assert(res.second && "attribute already exists");
}
///\brief Set an Attribute value, identified by its name. If it already exists, its value (and type, if different) is changed.
///\tparam T expected Attribute type
///\param name Attribute name
///\param value Attribute value
template<class T> void setAttr(const std::string& name, T&& value)
{
auto res = mAttrs.emplace(std::make_pair(name, libany::any(std::forward<T>(value))));
if (!res.second)
res.first->second = std::move(libany::any(std::forward<T>(value)));
}
//////////////////////////////////////
/// Generic Attributes API
//////////////////////////////////////
bool hasAttr(const std::string& name) const override final {
return (mAttrs.find(name) != mAttrs.end());
}
std::string getAttrType(const std::string& name) const override final {
return mAttrs.at(name).type().name();
}
std::vector<std::string> getAttrsName() const override final {
std::vector<std::string> attrsName;
for(auto const& it: mAttrs)
attrsName.push_back(it.first);
return attrsName;
}
#ifdef PYBIND
/**
* @detail See https://github.com/pybind/pybind11/issues/1590 as to why a
* generic type caster for std::any is not feasable.
*/
py::object getAttrPy(const std::string& name) const {
py::object res = py::none();
const auto& attrType = mAttrs.at(name).type();
if(attrType == typeid(int))
res = py::cast(getAttr<int>(name));
else if(attrType == typeid(float))
res = py::cast(getAttr<float>(name));
else if(attrType == typeid(bool))
res = py::cast(getAttr<bool>(name));
else if(attrType == typeid(std::string))
res = py::cast(getAttr<std::string>(name));
else if(attrType == typeid(std::vector<bool>))
res = py::cast(getAttr<std::vector<bool>>(name));
else if(attrType == typeid(std::vector<int>))
res = py::cast(getAttr<std::vector<int>>(name));
else if(attrType == typeid(std::vector<float>))
res = py::cast(getAttr<std::vector<float>>(name));
else if(attrType == typeid(std::vector<std::string>))
res = py::cast(getAttr<std::vector<std::string>>(name));
else {
throw py::key_error("Failed to convert attribute type " + name + ", this issue may come from typeid function which gave an unknown key : [" + attrType.name() + "]. Please open an issue asking to add the support for this key.");
}
return res;
};
#endif
private:
std::map<std::string, libany::any> mAttrs;
};
}
#endif /* AIDGE_CORE_UTILS_DYNAMICATTRIBUTES_H_ */