C++ 返回与参数常量相同的值

C++ 返回与参数常量相同的值,c++,constants,C++,Constants,我有一个带有这些重载的函数: A& f(B& b) { return b.a; } const A& f(const B& b) { return b.a; } return语句可以是一个更复杂的逻辑,如果b是const,则返回一个const值。例如,B是一个容器的容器(可能有更深的嵌套),我们正在搜索一个元素。在这种情况下,复制函数不是一个好主意。有没有其他方法可以达到同样的效果 我能想出一些解决办法,但我真的不喜欢 template <

我有一个带有这些重载的函数:

A& f(B& b)
{
    return b.a;
}

const A& f(const B& b)
{
    return b.a;
}
return语句可以是一个更复杂的逻辑,如果
b
是const,则返回一个const值。例如,
B
是一个容器的容器(可能有更深的嵌套),我们正在搜索一个元素。在这种情况下,复制函数不是一个好主意。有没有其他方法可以达到同样的效果

我能想出一些解决办法,但我真的不喜欢

template <typename T>
auto f(T& b) -> decltype(b.a)
{
    return b.a;
}

这也行,但如果感觉像黑客。有一个简单而干净的解决方案吗?

如果你知道
f
不会改变数据,那么
const\u cast
就不是一个黑客,而是一个完全合法的解决方案

典型的例子是
strchr
,它在字符串中查找字符。我们知道这不会发生变化,但通过提供非常量重载来允许可变字符串发生变化是非常明智的。然而,非常量版本可以很好地在常量重载方面实现


请记住,使用
const\u cast
并不违法。对常量对象进行变异只是一种违规行为。

我将以常量版本的形式实现非常量版本,而不是反过来(正如您所做的那样)

希望有帮助。

一个可能的解决方案:

template<typename B>
struct Return_type { typedef A &Type; };

template<typename B>
struct Return_type<B const &> { typedef A const &Type; };

template<typename B>
typename Return_type<B>::Type f(B &&b)
{
    return b.a;
}
模板
结构返回_type{typedef A&type;};
模板
结构返回_type{typedef A const&type;};
模板
类型名返回类型::类型f(B&&B)
{
返回学士学位;
}
编辑:

C++14将具有函数返回类型推断,因此这应该可以工作:

template<typename T>
auto &f(T &&b)
{
    return b.a;
}
模板
自动和f(T&b)
{
返回学士学位;
}

GCC4.8.1已经编译过了。

A&f(B&B){return f(const_cast(n));}呢?添加
const
不是一种黑客行为,您仍然可以得到所有的保证。我假设这个函数总是可以在const输入上工作,这个问题似乎暗示了这一点。然后我必须对输出进行const_转换,所以它基本上是一样的。但是是的,也许这样更安全。新型的typedef
使用Type=A const&看起来好多了。对于C++14解决方案,
auto
discard const?+1。我也想到了,但我只认为解决方案在C++11中有效。@Hulk:只适用于值,不适用于引用。例如,在
int const x=4中;自动y=x
y
的类型将是
int
,而不是
int const
。但在
int常量x=4;auto&y=x
y
的类型将是
int const&
。嗯,我想你是对的,非const版本应该根据const one实现。。。我总是搞不清楚哪种方法是正确的。对于
std::conditional
be
std::is_const::value
?@0x499602D2:它有一个隐式转换函数:
constepr操作符bool()const
。它将被隐式调用,并将自动获取
template <typename T>
auto f(T& b) -> std::conditional_t<std::is_const<T>{}, A const&, A&>
{
    return b.a;
}
typename std::conditional<std::is_const<T>{}, A const&, A&>::type
template<typename B>
struct Return_type { typedef A &Type; };

template<typename B>
struct Return_type<B const &> { typedef A const &Type; };

template<typename B>
typename Return_type<B>::Type f(B &&b)
{
    return b.a;
}
template<typename T>
auto &f(T &&b)
{
    return b.a;
}