使用运算符重载在 C++ 中创建函数式编程语法

Posted

技术标签:

【中文标题】使用运算符重载在 C++ 中创建函数式编程语法【英文标题】:Make functional programming syntax in c++ with operator overload 【发布时间】:2022-01-18 10:35:21 【问题描述】:
#include <MySyntax.hpp>
...

//let name1 = object;
//
//let name2 = object[ othervar1 , othervar2 , values val1, val2, val3... ];


let o3 = object [ values 1, "2", true, -3.14 ]; 
std::cout << o3; // prints: object [ “0”:1 , “1”:“2” , “2”:true , “3”:-3.14 ]

我希望在 中使用 c++11 实现这一点。 我在想letobject 的超类来实现初始化(只是我的第一个想法)。 在object 上还运算符重载[]&lt;&lt;。 但我不知道value 部分。 如果不清楚,value 右侧的任何内容都会放入一个集合中,并带有字符串编号索引(可能是 std::Map ?)。值可以是任何类型(对此也不知道,模板浮现在脑海中)。 任何讨论,资源链接,任何提示。只是想学习 C++ 惊人的可扩展性!

编辑:: 关键字value 是必需的。对象也将能够采用这种值 *再次参见代码块示例。一开始没有包括这个,因为这不是我最初的问题。我添加它只是为了强调values的使用。

【问题讨论】:

object [ values 1, "2", true, -3.14 ]; 多维下标运算符仅在C++23中有效。 我正在寻找在 C++ 中创建它。我知道它不标准。使用 c++ 元素,如 typedef, using, templates, operator overload, object orientation etc. 这看起来更像是一个javascript语法,基本上是::std::unordered_map&lt;::std::string, ::std::any&gt;; 【参考方案1】:

你可以使用std::tuple来存储各种类型并通过重载operator&lt;&lt;来打印它,并且通过重载C++23 multidimensional subscript operator来支持这种语法。

类似这样的:

#include<tuple>
#include<iostream>

template<class... Args>
using let = std::tuple<Args...>;

struct 
  template<class... Args>
  constexpr auto operator[](Args&&... args) const 
    return std::tuple(std::forward<Args>(args)...);
  
 object;

template<class... Args>
auto& operator<<(std::ostream& os, const std::tuple<Args...>& t) 
  return std::apply([&os, i = 0](auto& first, auto&... rest) mutable -> auto& 
    os << std::boolalpha << "[" << i++ << ":" << first;
    ((os << ", " << i++ << ":" << rest), ...);
    return os << "]";
  , t);


int main() 
  let o = object[1, "2", true, -3.14];
  std::cout << o;

Demo.

【讨论】:

使用 let 和你的操作符 [] 很好。【参考方案2】:

我认为你最好坚持标准库已经提供的内容。

您将重复使用经过测试的代码 其他人会发现您的代码更易于阅读。 无需让 C++ 看起来像 python、javascript(或任何其他语言),因为无论如何语言都有完全不同的哲学。

您的对象可以由 std::tuple 表示,然后代码将变为:

#include <iostream>
#include <string_view>
#include <tuple>

//-------------------------------------------------------------------------------------------------
// MySyntax.hpp

// helper function to put a heteroganous list of types into one datastructure
template<typename... args_t>
auto object(args_t&&... args)

    std::tuple<args_t...> obj std::forward<args_t>(args)... ;
    return obj;


// convert function for pretty printing
// normally convert to output type does nothing
template<typename type_t>
const type_t& convert(const type_t& value)

    return value;


// booleans should be outputed as text
std::string_view convert(const bool value)

    return value ? "true" : "false";


// output a tuple to stream
template<class type_t, size_t... index>
void output(std::ostream& os, const type_t& object, std::index_sequence<index...>)

    os << "[";
    // fold expression (so there is no need to create a recursive template function)
    (..., (os << (index == 0 ? "" : ", ") << "\"" << index << "\":" << convert(std::get<index>(object))));
    os << "]\n";


// overload stream operator for tuples
template<typename... args_t>
std::ostream& operator<<(std::ostream& os, const std::tuple<args_t...>& object)

    output(os, object, std::make_index_sequence<sizeof...(args_t)>());
    return os;


//-------------------------------------------------------------------------------------------------
// #include <MySyntax.hpp>


int main()

    // use auto instead of let
   auto o3 = object(1, 2.0, true, "hello");
   std::cout << "object " << o3;

   return 0;

【讨论】:

以上是关于使用运算符重载在 C++ 中创建函数式编程语法的主要内容,如果未能解决你的问题,请参考以下文章

C++语法小记---运算符重载

C++学习26 运算符重载的概念和语法

C++ 运算符重载三(链式编程)

C++学习:5其他语法

C++重载运算符

C++ 运算符重载