简体   繁体   English

隐藏 C++ 模板语法

[英]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:该解决方案有明显的缺点:

  1. Each pseudo field (as velocity) must have a pointer to Practice .每个伪场(如速度)必须有一个指向Practice的指针。
  2. Minimum one macro definition in a header. header 中至少有一个宏定义。
  3. Potential difficultness if you are going to use user-defined types.如果您要使用用户定义的类型,可能会遇到困难。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM