【问题标题】:Using template argument from universal reference as const ref使用来自通用引用的模板参数作为 const ref
【发布时间】:2014-07-25 18:59:12
【问题描述】:

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

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) 是否存在会失败的上下文?现在我觉得还不错。

【问题讨论】:

  • typedef typename std::add_reference&lt; typename std::add_const&lt; typename std::remove_reference&lt; T &gt;::type &gt;::type &gt;::type type; 嗯,为什么不只是using type = typename std::remove_reference&lt;T&gt;::type const&amp;;
  • "p1 也是算法的输出,因此如果调用者选择传入左值,函数将返回原始参数,修改后的参数以反映它停止的位置。" 退货不是一种选择吗?通常,返回更简洁,因为它不会产生副作用(使用元组返回多个值)。
  • "但是 p2 是同一类型,但永远不会被修改。" 它是否需要相同的 i> 类型?您还可以使用另一个模板参数加上 static_assert 或 SFINAE 检查它是否必须是 same 类型。
  • @dyp 其实我可以使用模板别名。直到最近我们还在 VS2012 上,所以它只是让我忘记了。谢谢 - 它使它更整洁。
  • 是的,但请注意,类型特征和其他类型函数(元函数)通常/按照约定是具有嵌套 typedef type 的类 (struct)。为方便起见,您可以提供 additional 别名模板,但为了更好的可重用性,我会坚持使用 Trait 的约定。

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


【解决方案1】:

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

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&lt;int&gt;(0, Foo{0})。如果您只希望完全匹配,那么这可能会有问题。在某些情况下,这是可取的; boost::clamp 是我知道的一个故意这样做的例子。

奖金

这类似于您问题的一些 cmets,但可以简化特征:

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

【讨论】:

    猜你喜欢
    • 2019-12-10
    • 2013-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-10
    • 2015-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多