Is there a reason declval returns add_rvalue_reference instead of add_lvalue_reference
With add_rvalue_reference
:
declval<Foo>()
is of typeFoo&&
.declval<Foo&>()
is of typeFoo&
(reference collapsing: “Foo& &&
” collapses toFoo&
).declval<Foo&&>()
is of typeFoo&&
(reference collapsing: “Foo&& &&
” collapses toFoo&&
).
With add_lvalue_reference
:
declval<Foo>()
would be of typeFoo&
.declval<Foo&>()
would be of typeFoo&
(reference collapsing: “Foo& &
” collapses toFoo&
).declval<Foo&&>()
would be of typeFoo&
(!) (reference collapsing: “Foo&& &
” collapses toFoo&
).
that is, you would never get a Foo&&
.
Also, the fact that declval<Foo>()
is of type Foo&&
is fine (you can write Foo&& rr = Foo();
but not Foo& lr = Foo();
). And that declval<Foo&&>()
would be of type Foo&
just feels “wrong”!
Edit: Since you asked for an example:
#include <utility>
using namespace std;
struct A {};
struct B {};
struct C {};
class Foo {
public:
Foo(int) { } // (not default-constructible)
A onLvalue() & { return A{}; }
B onRvalue() && { return B{}; }
C onWhatever() { return C{}; }
};
decltype( declval<Foo& >().onLvalue() ) a;
decltype( declval<Foo&&>().onRvalue() ) b;
decltype( declval<Foo >().onWhatever() ) c;
If declval
used add_lvalue_reference
you couldn't use onRvalue()
with it (second decltype
).
How does std::declval<T>() work?
Basically, in a sizeof
or decltype
expression you can call functions that aren't implemented anywhere (they need to be declared, not implemented).
E.g.
class Silly { private: Silly( Silly const& ) = delete; };
auto foo() -> Silly&&;
auto main() -> int
{
sizeof( foo() );
}
The linker should not complain about that.
How does std::is_assignable work?
Here's the same code with some of the lexical obfuscation taken out:
1043 template <typename Tp, typename Up>
1044 class is_assignable_helper
1046 {
1047 template <typename Tp1, typename Up1>
1048 static decltype(declval<Tp1>() = declval<Up1>(), one())
1049 test(int);
1050
1051 template<typename, typename>
1052 static two test(...);
1053
1054 public:
1055 static constexpr bool value = sizeof(test<Tp, Up>(0)) == 1;
1056 };
This class uses SFINAE to do the dirty work. That is, the value of variable value
will depend on which test()
function is chosen based on overload resolution. One overload takes an integer and the other takes a C variadic argument (specified by the ellipsis). If there is a substitution failure that occurs on the first overload, the second overload will be chosen.
If a substitution failure does occur, it will have come from the expression declval<Tp1>() = declval<Up1>()
. declval<T>()
is a function declaration that "returns" a value of the type std::add_rvalue_reference<T>::type
. This function is mainly used in unevaluated contexts like decltype()
, sizeof()
, noexcept()
, etc, in order to get an instance of a type without explicitly calling a constructor (because that type may not have an accessible constructor). If you'd like to know why add_rvalue_reference
is the chosen return type, see this post.
Once you get an instance of the type, you can call member/non-member functions on those instances. The member function used is operator=()
. If a class doesn't have an assignment operator (or has an inaccessible one) there will be a substitution failure. The fallback (variadic) version of test()
will instead be chosen.
The reason for the difference in argument types (int
vs ...
) is because ...
has the lowest conversion rank and it acts as a "last resort" for overload resolution. We can't just leave the parameters empty or else we'll get a redeclaration error.
As for the return type of test
- if a substitution failure does not occur (a value of type Up
can be assigned to a value of type Tp
) then test()
returns a type indicating success. If a substitution failure does happen, the the fallback version that returns a type indicating failure is chosen. These types are differentiated through a check for their sizes. We check for success by comparing with 1
.
result_of doesn't work for me
result_of is result_of<Fn(ArgTypes...)>
, not just result_of<Fn>
;
Try
typedef typename result_of<decltype(&f)()>::type result_free;
typedef typename result_of<decltype(&asd::f)(asd)>::type result_mem;
(works with gcc 4.6.2)
How do I conditionally install a file with WiX based on the target machine (32bit or 64bit)?
You could probably just do two separate components, using the conditions
VersionNT64
and
Not VersionNT64
But the correct way is to compile separate installers for 32 and 64 bit OS's and 64-bit components should also be marked as such (with Win64="yes"
) - I don't know if it's even possible to mark a Windows Installer package as targeted towards both Intel and x64. Only time I've ever done a mixed architecture installation is with NSIS, all my WiX installers have separate installers for each architecture.
Related Topics
VS 2012 - Project Failed to Build Because of Missing Toolset
May Volatile Be in User Defined Types to Help Writing Thread-Safe Code
Is There a Null Std::Ostream Implementation in C++ or Libraries
C++ Tips for Code Optimization on Arm Devices
C++ Template Instantiation: Avoiding Long Switches
Print Out the Values of a (Mat) Matrix in Opencv C++
Implementation of Operators for Enum Class
This Declaration Has No Storage Class or Type Specifier in C++
Direct Boost Serialization to Char Array
What Exactly Is Va_End For? Is It Always Necessary to Call It
Returning a "Null Reference" in C++
Can You Use Keyword Explicit to Prevent Automatic Conversion of Method Parameters
C++ Meta-Programming Doxygen Documentation