【问题标题】:Is it possible to pass variable template to function through lambda?是否可以通过 lambda 将变量模板传递给函数?
【发布时间】:2016-10-09 14:58:15
【问题描述】:

我知道如何pass template function as template argument,我现在正努力以类似的方式传递变量模板。

这是我尝试过的最小示例:

#define PASS_VARIABLE_TEMPLATE(name) [dummy=nullptr](auto&&...args) \
                                                    {return name<decltype(args)...>;}

//testing
template <typename T>
bool value = std::is_fundamental<T>::value;

template <typename Hax>
void print_bool(Hax h)
{
    std::cout << h(int{}) << std::endl; // no error, wrong output
    //std::cout << h(int{}, float{}) << std::endl; // error, good
}

int main()
{
    print_bool(PASS_VARIABLE_TEMPLATE(value)); //prints 0 instead of 1
}

Demo

如果可以编译,那为什么输出错误?

【问题讨论】:

  • 参考足够好吗?
  • @lorro 哦,傻我,忘了做腐烂!但另一方面,这会破坏引用/指针检查......也应该可以检查这种情况:int b; int&amp; ref = a; h(ref); //type is int&amp;
  • 你会得到预期的结果#define PASS_VARIABLE_TEMPLATE(name) [dummy=nullptr](auto&amp;&amp;args) { return name&lt;typename std::remove_reference&lt;decltype(args)&gt;::type&gt;; }
  • @SamVarshavchik 是的,但另一方面,如果改为应用std::is_rvalue_reference,它不会中断吗?

标签: c++ templates lambda c++14 variable-templates


【解决方案1】:

您的代码的主要问题是 decltype 将参数推断为 rvalue 引用 (int&amp;&amp;),因为您的 lambda 使用 转发引用 来接受参数。 std::is_fundamental 适用于 bare 类型。

对于您的具体sn-p,正确的解决方案是remove the reference

#define PASS_VARIABLE_TEMPLATE(name) \
    [dummy=nullptr](auto&&...args){return name<std::remove_reference_t<decltype(args)>...>;}

现在可以了。 :-) 看到Live On Coliru


一个稍微更多或更好的通用方法是额外添加remove cv 限定符。最后,你可能想使用std::decay

#define PASS_VARIABLE_TEMPLATE(name) [dummy=nullptr](auto&&...args) \
{return name<std::decay_t<decltype(args)>...>;}

【讨论】:

    【解决方案2】:
    template<class T>struct tag_t{using type=T; constexpr tag_t(){}};
    template<class Tag>using tagged_type=typename Tag::type;
    template<class T>constexpr tag_t<T> tag{};
    

    这些有助于将类型作为值传递并解包。

    #define PASS_VARIABLE_TEMPLATE(name) [](auto...args) \
                                                    {return name<tagged_type<decltype(args)>...>;}
    

    print_bool 里面你做的:

    std::cout << h(tag<int>) << std::endl;
    

    不知道你为什么要做dummy=nullptr 的事情。

    tag作为模板可以携带类型不受干扰。

    【讨论】:

    • dummy 是由于带有非捕获 lambda 的 GCC 错误(查看我在问题中发布的链接中接受的答案)。顺便说一句,很好的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-20
    • 2017-07-08
    • 2017-03-07
    • 1970-01-01
    • 1970-01-01
    • 2019-11-30
    相关资源
    最近更新 更多