定义特定函数

时间:2015-04-22 10:21:10

标签: c++ c++11 macros

我创建了一个声明为:

的函数
template <typename Container, typename Task>
void parallel_for_each(Container &container, Task task,
                       unsigned number_of_threads = std::thread::hardware_concurrency())

猜测它应该做什么并不难。我想创建一个宏来简化这个函数的语法,并使其语法“循环”。我想出了一个主意:

#define in ,
#define pforeach(Z,X,Y) parallel_for_each(X,[](Z)->void{Y;})

用法为:

pforeach(double &element, vec,
    {
     element *= 2;
    });

按预期工作,但这一个:

pforeach(double &element in vec,
    {
     element *= 2;
     element /= 2;
    });

给出错误

  

宏“pforeach”需要3个参数,但只有2个

您是否知道如何编写一个允许“更好”语法的宏?为什么“in”不代表我的代码中的逗号?

4 个答案:

答案 0 :(得分:4)

in未被替换的原因是它出现在类函数宏的参数内,但是要替换它,这些参数必须首先传播到另一个宏:尝试

#define in ,
#define pforeach_(Z,X,Y) parallel_for_each(X,[](Z)->void{Y;})
#define pforeach(Z,X,Y) pforeach_(Z,X,Y)

注意:将in定义为,并不会结束!

添加“更好”语法的想法:

template <typename Container>
struct Helper {
    Container&& c;
    template <typename Arg>
    void operator=(Arg&& arg) {
        parallel_for_each(std::forward<Container>(c), std::forward<Arg>(arg));
    }
};

#define CONCAT_(a,b) a##b
#define CONCAT(a,b) CONCAT_(a,b)
// Easier with Boost.PP
#define DEC_1 0
#define DEC_2 1
#define DEC_3 2
#define DEC_4 3
#define DEC_5 4
#define DEC_6 5
#define DEC_7 6
#define DEC_8 7
#define DEC(i) CONCAT(DEC_,i)

#define pforeach(Z, ...) \
  Helper<decltype((__VA_ARGS__))> CONCAT(_unused_obj, __COUNTER__){__VA_ARGS__}; \
  CONCAT(_unused_obj, DEC(__COUNTER__))=[](Z)

可用作

int a[] = {1, 2, 3};
pforeach(int i, a) {
    std::cout << i << ", ";
};

pforeach(int i, std::vector<int>{1, 2, 3}) {
    std::cout << -i << ", ";
};

Demo
但有几个缺点。我坚持你到目前为止所拥有的。

答案 1 :(得分:1)

  

为什么“in”不代表我的代码中的逗号?

因为在确定宏参数后执行了替换。引用标准草案N3797,§16.3.1参数替换:

  

在识别出类似函数的宏的调用参数之后,发生参数替换。 ...在被替换之前,每个参数的预处理标记都被完全宏替换,好像它们形成了预处理文件的其余部分;没有其他预处理令牌   可用。

因此预处理器将pforeach(double &element in vec, {})标识为具有两个参数的类函数宏调用:

  1. 首先包含令牌double&invec并绑定到参数Z
  2. 第二个包含令牌{}并绑定到参数X
  3. 你显然错过了论据Y

      

    您是否知道如何编写一个允许“更好”语法的宏?

    很难回答,这是味道的问题。无论如何,C ++具有丰富的修补语法与运算符重载的能力,但你不能用它来构建DSL,所以最好使用默认语法,它不是那么难看(并且也易于阅读):

     parallel_for_each(vec, [](double& el){ el *= 2; })
    

答案 2 :(得分:0)

没有宏的langugae。宏由C / C ++预处理器处理。预处理器的实现可能会有所不同。

大多数预处理器都希望您传递确切数量的参数。我发现GNU预处理器对参数的检查不太严格,它允许一种可变参数列表。但总的来说,宏不会帮助你完成任务。

我建议在函数中编写short语句而不是宏。内联函数与宏一样快和短,但类型安全。 此外,该功能允许默认参数值。所以你可以跳过一些东西。

答案 3 :(得分:0)

试图改进@Columbo的想法:

template <typename Container>
struct __pforeach__helper {
    Container &&c;
    template <typename Arg>
    void operator=(Arg&& arg) {
        parallel_for_each(std::forward<Container>(c), std::forward<Arg>(arg));
    }
};

//additional helper function
template <typename Container>
__pforeach__helper<Container> __create__pforeach__helper(Container &&c)
{
    return __pforeach__helper<Container>(__pforeach__helper<Container>{c});
}

#define pforeach(Z,C) \
  __create__pforeach__helper(C)=[](Z)

它不依赖于__COUNTER__,也不需要定义DEC_x个宏。欢迎任何反馈!