使用通用引用中的模板参数作为const引用

时间:2014-06-04 23:09:59

标签: c++ templates reference const universal-reference

我的实际用例需要更多参数,但它简化为:

template< typename Arg1 >
bool algorithm( Arg1&& p1, **p2 here** );

很明显,Arg1会以某种方式崩溃,并可能成为某种参考。 p1也是算法的输出,因此如果调用者选择传入左值,函数将返回并修改原始参数以反映它停止的位置。

然而,p2属于同一类型,但永远不会被修改。所以实际上我想在那里放一个'const'的承诺来保证正确性。显然,如果Arg1推断为参考,我不能添加const。

所以我的解决方案是:

template< class T >
struct make_const_ref
{
typedef typename std::add_reference< typename std::add_const< typename std::remove_reference< T >::type >::type >::type type;
};

template< typename Arg1 >
bool algorithm( Arg1&& p1, typename make_const_ref<Arg1>::type p2 );

通过一系列愚蠢的阴谋去除一些限定符,然后坚持const&amp;回来。

所以我的问题是:

1)这是最好的方式吗?

2)是否存在失败的背景?现在对我来说似乎很不错。

1 个答案:

答案 0 :(得分:0)

我可以想到一个令人惊讶的变化,但不会导致彻底的失败。从参数推导中禁用第二个参数,因此类型不再必须与第一个参数类型完全匹配。这允许接受隐式转换,如果为函数指定了模板参数。一个例子:

struct Foo
{
    int value;

    operator int() const
    {
        return value;
    }
};

int main()
{
    algorithm(0, Foo{0});
}

而表达式:

template<typename Arg>
bool algorithm(const Arg& p1, const Arg2& p2)
除非明确algorithm(0, Foo{0}),否则

将无法使用algorithm<int>(0, Foo{0})进行编译。如果你只希望完全匹配,那么这可能会有问题。在某些情况下这是可取的; boost::clamp是我所知道的一个有意识的例子。

加成

这与您的问题的一些评论类似,但可以简化特征:

template<typename Type>
using const_ref_t = 
    typename std::add_const<
        typename std::add_lvalue_reference<Type>::type>::type;

std::add_lvalue_reference会在所有情况下做你想做的事。

修改

我把它作为评论,但它可能应该放在这里。这可能更容易:

template<typename Arg1>
bool algorithm(Arg1&& p1, const typename std::remove_reference<Arg1>::type& p2)

您要做的就是禁用第二个参数的参数推导,并通过const-reference获取它。这就是这样做的。