【问题标题】:How can I write a decltype expression using a function that expects a non-const reference?如何使用需要非常量引用的函数编写 decltype 表达式?
【发布时间】:2015-06-11 15:43:28
【问题描述】:

考虑:

int convert_it(std::string& x)
{
    return 5;
}

void takes_int_ref(int& i)
{
}

我想写一个函数,它只有在convert_it 可以应用并且结果传递给takes_int_ref 时才存在。即函数体为:

template <typename A>
void doit(A& a) 
{
    int i = convert_it(a);
    takes_int_ref(i);
}

但是,如果我这样做:

template <typename A>
auto doit(A& a) -> decltype(takes_int_ref(convert_it(a)), void())

它不起作用,因为invalid initialization of non-const reference of type 'int&amp;' from an rvalue of type 'int'

我想到了以下可行的解决方案:

template <typename T>
T& gimme_ref(T t) { throw std::runtime_error("No"); return t; }

template <typename A>
auto doit(A& a) -> decltype(takes_int_ref(gimme_ref(convert_it(a))), void()) 

但是,这似乎很老套,decltype 不再反映函数体的作用。本质上问题似乎是decltype 只接受一个表达式,而这里的函数体中需要两个语句。

在这里采取什么正确的方法?

【问题讨论】:

  • std::result_ofstd::enable_if 有帮助吗?

标签: c++ templates c++11 decltype


【解决方案1】:

使用std::declval:

template <typename A>
auto doit(A& a) -> decltype(
    takes_int_ref(std::declval<
       decltype(convert_it(std::declval<A&>()))
       &>()), void())
{ .. }

std::declval&lt;A&amp;&gt;() 为您提供A&amp; 类型的表达式。 convert_it(A&amp;) 要么有效,要么无效——如果无效,你就会失败。如果它有效,就说它的类型为T。然后,您尝试使用T&amp; 调用takes_int_ref,以查看that 是否有效。如果是,您将访问void。如果不是,则替换失败。

【讨论】:

  • 这听起来正是我需要的!问题,为什么在 declval 表达式中需要&amp;s?
  • @Claudiu 因为你想要一个左值引用。 declval&lt;T&gt;() 给你一个T&amp;&amp;,但是declval&lt;T&amp;&gt;() 给你一个T&amp;
  • 有趣的是,这让我觉得我的版本不是那么 hackish,如果我只是将 gimme_ref 重命名为 ref_of 并且根本不定义正文,这看起来更干净:decltype(takes_int_ref(ref_of(convert_it(a))), void())
  • @Claudiu 是的。我想std::declval&lt;A&amp;&gt;() 也不是必需的,因为a 已经是A&amp;。我想我只是把它放在那里是为了无偿。是的,让我们一起去吧。
【解决方案2】:

为了记录,在看到 std::declval 解决方案后,我对什么是 hackish 的看法发生了变化,我最终选择了这个:

template <typename T> T& lref_of(T&&);

template <typename A>
auto doit(A& a) -> decltype(takes_int_ref(lref_of(convert_it(a))), void()) 
{ .. }

由于我是从表达式而不是类型开始的,所以lref_of(convert_it(a))std::declval&lt;decltype(convert_it(a))&amp;&gt;() 更简洁。另外,如果在任何代码中使用它而不是定义 lref_of 会产生编译时错误,这比将其定义为在运行时简单地抛出异常要好。

【讨论】:

    猜你喜欢
    • 2014-03-27
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多