模板中为paser使用typename指定dependent name

chromium中广泛使用的bind模板, 

// Bind as RepeatingCallback.
template <typename Functor, typename... Args>
inline RepeatingCallback<MakeUnboundRunType<Functor, Args...>>
BindRepeating(Functor&& functor, Args&&... args) {
  static_assert(
      !internal::IsOnceCallback<std::decay_t<Functor>>(),
      "BindRepeating cannot bind OnceCallback. Use BindOnce with std::move().");

  // This block checks if each |args| matches to the corresponding params of the
  // target function. This check does not affect the behavior of Bind, but its
  // error message should be more readable.
  using Helper = internal::BindTypeHelper<Functor, Args...>;
  using FunctorTraits = typename Helper::FunctorTraits;
  using BoundArgsList = typename Helper::BoundArgsList;
  using UnwrappedArgsList =
      internal::MakeUnwrappedTypeList<false, FunctorTraits::is_method,
                                      Args&&...>;
  using BoundParamsList = typename Helper::BoundParamsList;
  static_assert(internal::AssertBindArgsValidity<
                    std::make_index_sequence<Helper::num_bounds>, BoundArgsList,
                    UnwrappedArgsList, BoundParamsList>::ok,
                "The bound args need to be convertible to the target params.");

  using BindState = internal::MakeBindStateType<Functor, Args...>;
  using UnboundRunType = MakeUnboundRunType<Functor, Args...>;
  using Invoker = internal::Invoker<BindState, UnboundRunType>;
  using CallbackType = RepeatingCallback<UnboundRunType>;

  // Store the invoke func into PolymorphicInvoke before casting it to
  // InvokeFuncStorage, so that we can ensure its type matches to
  // PolymorphicInvoke, to which CallbackType will cast back.
  using PolymorphicInvoke = typename CallbackType::PolymorphicInvoke;
  PolymorphicInvoke invoke_func = &Invoker::Run;

  using InvokeFuncStorage = internal::BindStateBase::InvokeFuncStorage;
  return CallbackType(BindState::Create(
      reinterpret_cast<InvokeFuncStorage>(invoke_func),
      std::forward<Functor>(functor), std::forward<Args>(args)...));
}

 

Reasons:http://www.cplusplus.com/forum/general/219039/

The C++ grammar is heavily context sensitive; for instance: name_a * name_b ; would be multiplication if name_ais the name of a non-type and the declaration of a pointer if name_a is the name of a type.

In normal code, the parser manages this by classifying names: before name_a is used, it must be declared and the parser can keep track of what exactly name_a is.

With templates, the situation becomes more involved: when the template 
(say template < typename T > void foo( T& object ) { /* ... T::dependant_name ... */ } is parsed for the first time, the classification for T::dependant_name is not available. In addition, what a dependent name is may be changed by an explicit specialisation, which need not be visible during phase one.

One alternative would have been to avoid two-phase name lookup altogether, and defer look up of all names to the time when the template is instantiated. (Btw, this is more or less what the still-non-conforming-in-this-regard microsoft implementation does.) In addition to being less efficient, this could also lead to edge-cases where the meaning of a non-dependent name (that was intended by the template author) could be changed depending on where the template was instantiated from.

Therefore, the alternative that was adopted is to classify the names in a template into two distinct genres: dependent names and non-dependent names, and to resolve non-dependent names during the first phase (when the template definition is first seen). This would require that we give some minimal context to the parser about what a dependent name is; ergo the need for typename and template disambiguators for dependent names.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值