在variadic模板中更好地打包扩展语法?

时间:2015-03-24 17:56:11

标签: c++ templates c++11 variadic-templates

谈论已经一成不变的语言语法可能效率不高。

但是,我想知道为什么C++11 variadic template's argument expansion在某些嵌套用法方面无法更明确地阅读

例如,我认为C ++开发人员通常可以更清楚地编写如下代码。 (如果允许的话)

template<typename ...> struct Tuple 
{

};

template<typename T1, typename T2> struct Pair 
{

};

template<class ...Args1> struct zip 
{
    template<class ...Args2> struct with 
    {   
        typedef Tuple<Pair<Args1, Args2>...> type;

        // More code but but maybe better readability?
        // because Args1, and Args2 are the ones that get 
        // actually expanded, not Pair<T1, T2>.
        // typedef Tuple<Pair<Args1..., Args2...>> type; // ## Invalid! ##
    };
};


typedef zip<short, int>::with<unsigned short, unsigned>::type T1;

通过这样做,我们真的不必混淆哪些模板类型正在被扩展,或者应该是在进行多嵌套variadic template时必须扩展的模板类型,因为它变得更加重要让你的代码看起来比缩短更清晰。

另外,我喜欢以与调用函数相同的方式查看代码,如下所示:

Foo(args...); // Okay.

我们不这样做:

Foo(args)...; // Error.

修改

我相信这个应该至少被允许工作得很好。

Tuple<Pair<Args1..., Args2...>> // Invalid code.

但事实并非如此。

为什么不呢? 是否存在任何潜在的风险来说服委员会足以阻止其编制?

提前非常感谢你。

1 个答案:

答案 0 :(得分:2)

在您的每一个案例中,您的“首选”符号都会与您想要的不同扩展。它们无效。

如果Args0 = {a,b,c}和Args1 = {int,double,char},那么:

std::tuple< foo< Args0..., Args1... > >

std::tuple< foo< a,b,c,int,double,char > >

,而

std::tuple< foo< Args0, Args1>... >

std::tuple< foo< a, int >, foo< b, double >, foo< c, char > >

问题是,这些都是有用的操作。

关键是...对可能扩展的子“表达式”进行操作,而不是直接对包进行操作。

除非您提出的符号可以产生这两种结果,否则它是一种较弱的符号。

Foo(Args)...Foo(Args...)也是如此。它们不是说话的替代方式 - 它们是在当前C ++中说两种不同的东西的方式。你的计划在第二个意思是第一个,这意味着你不再能够表达你的C ++版本中第二个含义。

每次扩展都有两个部分。第一个是正在扩展哪些包,第二个是正在扩展的“表达式”。在当前的C ++中,正在扩展的包都是表达式中未展开的包:它们没有标记。

在您的版本中,您将包标记为展开,并且从不标记要展开的表达式。如果这种语言能够读懂你的想法,它就可以找出那个表达式的位置,但是阅读你的思维的编程语言通常是一个坏主意。

“标记表达而不是包装”的副作用是你可以做一些非常强大的东西,比如让整个lambda包含在体内的表达式内的未扩展包,然后生成一包lambdas。在你的系统中表达这将是一项挑战。