[英]Hiding C++ template syntax
There is a class Particle with a method template property , which represents a reference to a primitive type.有一个带有方法模板属性的 class Particle ,它表示对原始类型的引用。
particle.template property<velocity>() = 0.0;
The syntax should be more readable.语法应该更具可读性。 The goal is something like:
目标是这样的:
particle.velocity = 0.0;
I think this could be possible using pre-processor macros or TMP libraries like Boost.Hana.我认为这可以使用预处理器宏或 TMP 库(如 Boost.Hana)来实现。 But I didn't manage to make it work, yet.
但我还没有设法让它发挥作用。
Context: I am working on an embedded C++ DSL and want to make it easier to use for people unfamiliar with programming.上下文:我正在研究嵌入式 C++ DSL,并希望它更容易被不熟悉编程的人使用。
I have not worked with Boost.Hana but I can suggest this idea.我没有使用过 Boost.Hana,但我可以提出这个想法。 Maybe useful.
也许有用。
#include <iostream>
#define DECL(type, name) \
struct name##_t \
{ \
Practice* p; \
operator type&(); \
Practice::name##_t& operator= (type);\
} name;
#define IMPL(type, name) \
Practice::name##_t::operator type&() \
{ \
return p->property<type, name##_t>(); \
} \
Practice::name##_t& Practice::name##_t::operator= (type x)\
{ \
p->property<type, name##_t>() = x; \
return *this; \
}
struct Practice
{
template<class D, class T> D& property();
Practice(): velocity{ this }
{
}
DECL(double, velocity);
// struct velocity_t
// {
// Practice* p;
// operator double&();
// void operator= (double);
// } velocity;
};
template <>
double& Practice::property<double, Practice::velocity_t>()
{
static double v;
return v;
}
IMPL(double, velocity);
// Practice::velocity_t::operator double&()
// {
// return p->property<double, velocity_t>();
// }
// Practice::velocity_t& Practice::velocity_t::operator= (double x)
// {
// p->property<double, velocity_t>() = x;
// return *this;
// }
int main()
{
Practice practice;
practice.velocity = 4.8;
std::cout << practice.velocity;
return 0;
}
The solution has clear disadvantages:该解决方案有明显的缺点:
Practice
.Practice
的指针。 UPD: I developed the idea. UPD:我提出了这个想法。
Now you have not to write more then you need.现在你不必写得比你需要的多。 Just declare your fields and specialize
property
for them.只需声明您的字段并为它们专门化
property
。 But it works since C++17.但它从 C++17 开始工作。
#include <iostream>
#include <string>
struct Practice;
template<class Field, class T = typename Field::type>
struct PseudoField
{
using type = T;
Practice& p;
operator type& ();
decltype(auto) get() { return static_cast<type&>(*this); }
type* operator->() { return &get(); }
template<class D>
PseudoField& operator= (D &&);
};
#define DECL(type, name) \
struct name##_t : PseudoField<name##_t, type> \
{ \
using PseudoField::operator=; \
} name { *this }
struct Practice
{
template<class T, class D> D& property();
DECL(double , velocity);
DECL(std::string , name);
};
template<class Field, class T>
PseudoField<Field, T>::operator T&()
{
return p.property<Field, T>();
}
template<class Field, class T> template<class D>
PseudoField<Field, T>&
PseudoField<Field, T>::operator= (D && x)
{
p.property<Field, T>() = std::forward<D>(x);
return *this;
}
template <>
Practice::velocity_t::type&
Practice::property<Practice::velocity_t>()
{
static double v;
return v;
}
template <>
Practice::name_t::type&
Practice::property<Practice::name_t>()
{
static std::string v;
return v;
}
int main()
{
Practice practice;
practice.velocity = 4.8;
practice.name = "hello!";
auto moved = std::move(practice.name.get());
std::cout << "velocity: " << practice.velocity << std::endl
<< "moved name: " << moved << std::endl
<< "src name length: " << practice.name->size()<< std::endl;
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.