如何使用需要非const引用的函数编写decltype表达式?

Cla*_*diu 5 c++ templates decltype c++11

考虑:

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

void takes_int_ref(int& i)
{
}
Run Code Online (Sandbox Code Playgroud)

我想编写一个函数,只有在convert_it可以应用并传递结果时才存在takes_int_ref.也就是说,功能体是:

template <typename A>
void doit(A& a) 
{
    int i = convert_it(a);
    takes_int_ref(i);
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我这样做:

template <typename A>
auto doit(A& a) -> decltype(takes_int_ref(convert_it(a)), void())
Run Code Online (Sandbox Code Playgroud)

它不起作用,因为invalid initialization of non-const reference of type 'int&' 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()) 
Run Code Online (Sandbox Code Playgroud)

然而,它似乎是hackish,decltype不再反映功能体的作用.从本质上讲,问题似乎decltype只是表达式,而函数体中需要两个语句.

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

Bar*_*rry 9

用途std::declval:

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

std::declval<A&>()给你一个类型的表达A&.convert_it(A&)是否有效 - 如果它无效,你就失败了.如果它有效,请说它有类型T.然后,您尝试调用takes_int_ref同一个T&,所以,看看的有效.如果是的话,你会到达void.如果不是,替换失败.