Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
299 views
in Technique[技术] by (71.8m points)

c++ - What are some uses of decltype(auto)?

In c++14 the decltype(auto) idiom is introduced.

Typically its use is to allow auto declarations to use the decltype rules on the given expression.

Searching for examples of "good" usage of the idiom I can only think of things like the following (by Scott Meyers), namely for a function's return type deduction:

template<typename ContainerType, typename IndexType>                // C++14
decltype(auto) grab(ContainerType&& container, IndexType&& index)
{
  authenticateUser();
  return std::forward<ContainerType>(container)[std::forward<IndexType>(index)];
}

Are there any other examples where this new language feature is useful?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Return type forwarding in generic code

For non-generic code, like the initial example you gave, you can manually select to get a reference as a return type:

auto const& Example(int const& i) 
{ 
    return i; 
}

but in generic code you want to be able to perfectly forward a return type without knowing whether you are dealing with a reference or a value. decltype(auto) gives you that ability:

template<class Fun, class... Args>
decltype(auto) Example(Fun fun, Args&&... args) 
{ 
    return fun(std::forward<Args>(args)...); 
}

Delaying return type deduction in recursive templates

In this Q&A a few days ago, an infinite recursion during template instantiation was encountered when the return type of the template was specified as decltype(iter(Int<i-1>{})) instead of decltype(auto).

template<int i> 
struct Int {};

constexpr auto iter(Int<0>) -> Int<0>;

template<int i>
constexpr auto iter(Int<i>) -> decltype(auto) 
{ return iter(Int<i-1>{}); }

int main() { decltype(iter(Int<10>{})) a; }

decltype(auto) is used here to delay the return type deduction after the dust of template instantiation has settled.

Other uses

You can also use decltype(auto) in other contexts, e.g. the draft Standard N3936 also states

7.1.6.4 auto speci?er [dcl.spec.auto]

1 The auto and decltype(auto) type-speci?ers designate a placeholder type that will be replaced later, either by deduction from an initializer or by explicit speci?cation with a trailing-return-type. The auto type-speci?er is also used to signify that a lambda is a generic lambda.

2 The placeholder type can appear with a function declarator in the decl-specifier-seq, type-specifier-seq, conversion-function-id, or trailing-return-type, in any context where such a declarator is valid. If the function declarator includes a trailing-return-type (8.3.5), that specifies the declared return type of the function. If the declared return type of the function contains a placeholder type, the return type of the function is deduced from return statements in the body of the function, if any.

The draft also contains this example of variable initialization:

int i;
int&& f();
auto x3a = i;                  // decltype(x3a) is int
decltype(auto) x3d = i;        // decltype(x3d) is int
auto x4a = (i);                // decltype(x4a) is int
decltype(auto) x4d = (i);      // decltype(x4d) is int&
auto x5a = f();                // decltype(x5a) is int
decltype(auto) x5d = f();      // decltype(x5d) is int&&
auto x6a = { 1, 2 };           // decltype(x6a) is std::initializer_list<int>
decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression
auto *x7a = &i;                // decltype(x7a) is int*
decltype(auto)*x7d = &i;       // error, declared type is not plain decltype(auto)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...