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.