0

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

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& 。

所以我的问题是:

1)这是最好的方法吗?

2) 是否存在这将失败的上下文?现在对我来说似乎还不错。

4

1 回答 1

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 获取它。这就是这样做的。

于 2014-06-05T03:45:57.647 回答