If there are no another overloadings (say, f(T &) or f(volatile T &&)) of a (member) function template template< typename T > f(T &&);, then T && is so-called forwarding reference, and T is either U, or U & for some cv-qualified type U. But for cv-ref-qualifiers of member functions there is no such a rule. In struct S { void f() && { ; } }; a S::f() has always rvalue-reference qualifier.
In generic code it would be very useful to avoid a definition of 4 (or even 8, if we also consider volatile qualifier) overloadings of some member function, in cases if all of them doing generally the same thing.
Another problem that arises in this way, it is impossibility to define an effective cv-ref-qualifier of *this in a particular sense. Following code not allows one to determine whether the ref-qualifier of a member function operator () is && of &.
#include <type_traits>
#include <utility>
#include <iostream>
#include <cstdlib>
#define P \
{ \
using this_ref = decltype((*this)); \
using this_type = std::remove_reference_t< this_ref >; \
std::cout << qual() << ' ' \
<< (std::is_volatile< this_type >{} ? "volatile " : "") \
<< (std::is_const< this_type >{} ? "const " : "") \
<< (std::is_lvalue_reference< this_ref >{} ? "&" : "&&") \
<< std::endl; \
}
struct F
{
constexpr int qual() & { return 0; }
constexpr int qual() const & { return 1; }
constexpr int qual() && { return 2; }
constexpr int qual() const && { return 3; }
constexpr int qual() volatile & { return 4; }
constexpr int qual() volatile const & { return 5; }
constexpr int qual() volatile && { return 6; }
constexpr int qual() volatile const && { return 7; }
void operator () () & P
void operator () () const & P
void operator () () && P
void operator () () const && P
void operator () () volatile & P
void operator () () volatile const & P
void operator () () volatile && P
void operator () () volatile const && P
};
int
main()
{
{
F v;
F const c{};
v();
c();
std::move(v)();
std::move(c)();
}
{
volatile F v;
volatile F const c{};
v();
c();
std::move(v)();
std::move(c)();
}
return EXIT_SUCCESS;
}
But it would be very nice, if there was above syntax. I.e. decltype((*this)) denote exact cv-ref-qualified type of *this. It would not be a breaking-change to introduce such a syntax into coming version of the C++ standard at my mind. But && as forwarding cv-ref-qualifier is (and it looks like an omission of the committee (namely, core language working group)).
Another sequence is possible to denote both the member function cv-ref-qualifier and cv-ref-qualified type of *this into its body: auto &&, decltype(&&) etc.
Is there a proposal regarding this issue, prepared for use in C++17?
Yes, there are such proposals.
Background:
Since we already have forwarding references in template functions, you could simply turn your member function into a template friend function (and protect it via enable_if from being used with any other class than F, if required).
Now, maybe you want your really, really want to use your function as a member function, because you really, really like that syntax so much better.
The proposals:
Look up unified call syntax proposals, for instance: n4174
If something like that is accepted, it you will be able to use free functions like member functions of the first argument. This would cover the example code you linked in your first comment. Admittedly, it would not cover operator(), but I consider that a minor nuisance compared to writing 8 overloads :-)
Related
Is it possible to write a function or method which can return a pointer to a template function or template method?
Example:
#include <iostream>
struct X1 {
static void Do(auto n) { std::cout << "1" << n << std::endl; }
// static auto GetPtr() { return X1::Do; } // how to write such a function?
};
struct X2 {
static void Do(int n) { std::cout << "2" << n << std::endl; }
//static auto GetPtr(){ return &Do; }
};
template <typename T> T magic(bool b, T t1, T t2) { return b ? t1 : t2; }
int main() {
auto l1 = magic(true, X1::Do, X2::Do);
// should be replaced by:
// auto l1 = magic( true, X1::GetPtr(), X2::GetPtr() );
l1(100);
}
If I compile the above out-commented functions, I got from gcc:
main.cpp:1845:39: error: unable to deduce 'auto' from 'X1::Do'
Background: I am currently trying to understand the overload resolution in same cases. In the given case you see that the overload for int is taken because one function pointer only has an int parameter so the second pointer overload can be found.
I was triggered by that question: Ternary operator applied to different lambdas produces inconsistent results
Here in an answer was suggested, that a lambda should be able to provide a conversion operator to a function pointer... and I did not see it :-)
The compiler doesn't "know" in advance all your uses for X1::GetPtr (generally). It seems you are expecting the compiler to 1. recognize it is a template 2. recognize all uses for the function, and see if it can deduce all instantiations needed for the template "for free", so to speak - in your case only the use in magic, but this is not general.
There is no such mechanism in C++ and the compiler must know the type of the function when it parses it, or recognize it as a template (and not guess it).
Simply put, I think you are expecting the compiler to do something too difficult, and it can't. As such, you will have to do the template resolution yourself:
template<typename N>
static auto GetPtr() { return &X1::Do<N>; }
and call it with
magic(true, X1::GetPtr<int>(), X2::GetPtr());
No you cannot return a pointer to a function template, because a function template is not a function. It is a template.
// static auto GetPtr() { return X1::Do; } // how to write such a function?
You need & to get a pointer to a member function, though Do is not a member function it is a member function template. You could return a pointer to X1::Do<int> or to X1::Do<double> but there is no pointer to X1::Do.
You can however return a functor with an overloaded call operator and that operator can be a template:
struct foo {
template <typename T>
void operator()(const T& t) {}
void operator()(int x){}
};
foo magic() { return foo{}; }
int main() {
magic()(3); // calls operator()(int)
magic()("hello world"); // calls operator()<const char[12]>
}
After rereading your question and the Q&A you link, I think you are maybe looking for this:
#include <iostream>
struct X1 {
static void Do(auto n) { std::cout << "1" << n << std::endl; }
static auto GetPtr() { return &X1::Do<int>; }
};
struct X2 {
static void Do(int n) { std::cout << "2" << n << std::endl; }
static auto GetPtr(){ return &Do; }
};
template <typename T> T magic(bool b, T t1, T t2) { return b ? t1 : t2; }
int main() {
auto l1 = magic( true, X1::GetPtr(), X2::GetPtr() );
l1(100);
}
As stated above, you cannot get a member function pointer to X1::Do but you can get a pointer to X1::Do<int>.
And as you are refering to conversion of lambdas to function pointers: Also lambdas with auto argument can only be converted to function pointers after choosing the argument type. Consider the example from cppreference:
void f1(int (*)(int)) {}
void f2(char (*)(int)) {}
void h(int (*)(int)) {} // #1
void h(char (*)(int)) {} // #2
auto glambda = [](auto a) { return a; };
f1(glambda); // OK
f2(glambda); // error: not convertible
h(glambda); // OK: calls #1 since #2 is not convertible
int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK
It is not possible to get a pointer to function of type auto(auto) (it isn't a type of a function to begin with). In all the calls above, after the conversion there is no auto anymore. Instead the requested type is deduced and a conversion to the respective function pointer is done.
Improper support of volatile-qualified overloadings of member functions in STL prevents using of containers, smart pointers, etc in generic way. Say, I want to declare a wrapper class, that provides value semantics and allows incompleteness of underlying type:
#include <type_traits>
#include <utility>
#include <memory>
template< typename type >
struct recursive_wrapper
{
using value_type = type;
template< typename ...arguments >
recursive_wrapper(arguments &&... _arguments)
: storage_(std::make_unique< type >(std::forward< arguments >(_arguments)...))
{ ; }
operator type & () & noexcept
{
return *storage_;
}
operator type const & () const & noexcept
{
return *storage_;
}
operator type && () && noexcept
{
return std::move(*storage_);
}
operator type const && () const && noexcept
{
return std::move(*storage_);
}
operator volatile type & () volatile & noexcept
{
return *storage_;
}
operator volatile type const & () volatile const & noexcept
{
return *storage_;
}
operator volatile type && () volatile && noexcept
{
return std::move(*storage_);
}
operator volatile type const && () volatile const && noexcept
{
return std::move(*storage_);
}
private :
std::unique_ptr< type > storage_;
};
// file:main.cpp
#include <iostream>
#include <vector>
#include <cstdlib>
int
main()
{
struct A;
struct B { recursive_wrapper< A > a; };
struct A { std::vector< B > b; };
{ // basic usage
B b;
A & a = b.a; // OK
static_cast< void >(a);
}
// let's add cv-qualifiers
{
volatile B b;
volatile A & a = b.a; // error!
static_cast< void >(a);
}
return EXIT_SUCCESS;
}
Lack of appropriate volatile-qualified overloading of std::unqie_ptr::operator * () causes an error:
main.cpp:38:16: error: indirection requires pointer operand ('volatile std::unique_ptr<A>' invalid)
return *storage_;
^~~~~~~~~
main.cpp:83:30: note: in instantiation of member function 'recursive_wrapper<A>::operator volatile A &' requested here
volatile A & a = b.a;
^
1 error generated.
The same story WRT std::container::push_back(), size(), etc.
It totally prevents a using of objects of STL (not involving const_cast operator) in generic code, which uses volatile member-function qualifier.
What is a reason of such poor STL design decision? Why volatile member function qualifier not properly supported in STL?? Is volatile member function qualifier depricated?
It's a very good decision. It's because volatility would be outright wrong for most types.
Keep in mind that volatile on an object means the object's fields can mutate spontaneously.
Consider the following, and assume the system guarantees that, at any given instant, begin and end will point to the same memory block:
template<class T>
class vector
{
T *begin;
T *end;
vector(vector const volatile &other) : begin(other.begin), end(other.end) { ... }
};
It turns out vector::vector(vector const volatile &) is wrong, because it cannot ensure that begin and end are read simultaneously.
Consequently, the copy it creates might have a begin and end that are out of sync, even though the original was completely fine.
I think this should be enough to make you realize why volatile is barely used.
It simply isn't used for the same reason that you were probably expecting used (i.e. atomics).
Its use case is entirely different and uncommon, and it is not something you throw around on a whim the way you might with const.
"Poor design decision"? Not really. The keyword is inherited from C, but there is very little use for it today. It's not actively deprecated, but its main use is in simple cases. Memory-mapped hardware would be a good example. But there won't be a memory-mapped std::deque<> so there's little point in STL support for that.
There is a class C with methods foo, boo, boo_and_foo and foo_and_boo. Each method takes i,j,k and l clock cycles respectively, where i < j, k < i+j and l < i+j.
class C
{
public:
int foo() {...}
int boo() {...}
int boo_and_foo() {...}
int foo_and_boo() {...} };
In code one might write:
C c;
...
int i = c.foo() + c.boo();
But it would be better to have:
int i = c.foo_and_boo();
What changes or techniques could one make to the definition of C, that would allow similar syntax of the original usage, but instead have the compiler generate the latter.
Note that foo and boo are not commutative.
Idea 1 Thanks the comments!
I was thinking creater a cHelper class, and a cOps class with string member ops, so that after have cHelper ch;, we can write int i = ch.foo() + ch.boo();
ch.foo() does nothing but returns: cOps("foo")
ch.boo() also only returns: cOps("boo")
overload "+" operator for cOps class so that cOps("foo") + cOps("boo") actually returns cOps("foo,boo")
overload the int type conversion operator of cOps so that int i = cOps("foo") ; actually calls c.foo(); while int i = cOps("foo,boo") ; actually calls c.foo_and_boo();
A bit ugly ....
The objective sounds rather similar to what Todd Veldhuizen pioneered many moons ago for Blitz++: aggregating operations effectively into an expression tree to effectively change the order of computations. In the case of Blitz++ it was done for matrix operations. The technique is known as Expression Templates.
The overall idea would not be to aggregate a string and its operations, though, but rather to encode the necessary operations in the type returned. Similar to what is described in the question the evaluation of the expression is delayed until they are needed. By using specializations for specific operations the compiler would be made to choose the appropriate combations. It could look somewhat like this:
#include <iostream>
namespace C_ops { struct C_tag {}; }
struct C_foo;
struct C_bar;
class C: C_ops::C_tag {
int value;
public:
explicit C(int value): value(value) {}
C_foo foo() const;
C_bar bar() const;
int actual_foo() const {
std::cout << "compute foo(" << value << ")\n";
return value;
}
int actual_bar() const {
std::cout << "compute bar(" << value << ")\n";
return value;
}
int foo_and_bar(C const& r) const {
std::cout << "compute foo_and_bar(" << this->value << ", " << r.value << ")\n";
return this->value;
}
int bar_and_foo(C const& r) const {
std::cout << "compute bar_and_foo(" << this->value << ", " << r.value << ")\n";
return this->value;
}
};
struct C_foo: C_ops::C_tag {
C const& c;
C_foo(C const& c): c(c) {}
operator int() const { return c.actual_foo(); }
};
struct C_bar: C_ops::C_tag {
C const& c;
C_bar(C const& c): c(c) {}
operator int() const { return c.actual_bar(); }
};
C_foo C::foo() const { return C_foo(*this); }
C_bar C::bar() const { return C_bar(*this); }
template <typename L, typename R>
struct C_add;
template <>
struct C_add<C_foo, C_bar> {
C_foo l;
C_bar r;
C_add(C_foo const& l, C_bar const& r): l(l), r(r) {}
operator int() const { return l.c.foo_and_bar(r.c); }
};
template <>
struct C_add<C_bar, C_foo> {
C_bar l;
C_foo r;
C_add(C_bar const& l, C_foo const& r): l(l), r(r) {}
operator int() const { return l.c.bar_and_foo(r.c); }
};
// more specializations, e.g., to deal with C on the LHS
namespace C_ops {
template <typename L, typename R>
C_add<L, R> operator+(L const& l, R const& r) {
return C_add<L, R>(l, r);
}
}
template <typename... T> void use(T const&...) {}
int main()
{
C c0(0), c1(1);
int r0 = c0.foo();
int r1 = c0.bar();
int r2 = c0.foo() + c1.bar();
int r3 = c0.bar() + c1.foo();
std::cout << "done\n";
use(r0, r1, r2, r3); // make them used to not have them optimized away (for now)
}
With the setup above, the four expressions you mentioned would be covered. There are probably more specializations needed, e.g., to all c + c.foo(), c + c, etc. but the overall principle doesn't really change. You may want to protect actual_foo() and actual_bar() from being accessed and making the respective classes needing to call the friends.
The need for the extra namespace C_ops is merely to provide "catch-all" operators which hijack operator+() for all types, as long as they happen to be loooked up in this namespace. To do so, there is also a tag-type which has no other purpose than directing ADL (argument dependent look-up) to look into this namespace.
This is quite a cute technique which worked rather reliably with C++03: since the expressions are evaluated when the target type (in the above case int) is needed and C++03 didn't really allow for capturing the intermediate type while potentially involved temporary object were not around any more (the only was to catch the expression type in a deduced context would be when passing it to a function template) there were no life-time issues. With C++11 it is to capture the type of objects using auto which would capture the expression type, not evaluated result, there is probably some need to think properly about life-time of involved objects. The above example just used const objects but you'll probably need to be more careful and prevent certain temporary objects from being capture, primarily objects of type C. From your descriptions it isn't clear whether these would be expensive objects: the ideal solution would be to capture all objects by value but that may be too expensive.
I am trying to understand the trailing return based new function declaration syntax in C++11, using decltype.
In the following code, I am trying to define a member function returning a const & to allow for read-only access to i
#include <iostream>
#include <type_traits>
struct X {
int &i;
X(int &ii) : i(ii) {}
// auto acc() const -> std::add_const<decltype((i))>::type { return i; } // fails the constness test
auto acc() const -> decltype(i) { return i; } // fails the constness test
// const int &acc() const { return i; } // works as expected
};
void modify_const(const X &v) {
v.acc() = 1;
}
int main() {
int i = 0;
X x(i);
modify_const(x);
std::cout << i << std::endl;
return 0;
}
As mentioned in the comments, only the last commented version of acc() works, whereas using the others, the code just compiles and prints value 1.
Question: How do we have to define the acc() function using the new function declaration syntax based on decltype, such that the compilation here fails due to returning a const &int in modify_const, or in other words, such that acc() has a proper const &int return type.
Remark: using int i; instead of int &i; as the member variable in X produces a compile error, as expected.
Edited to better distinguish between constness of v and X::i, respectively. It is the latter I am trying to impose in acc().
The problem is that decltype((i)) return int& and apply const to that type has no effect. You want something like
template <typename T> struct add_ref_const { typedef T const type; };
template <typename T> struct add_ref_const<T&> { typedef T const& type; };
... and then use
auto acc() const -> typename add_ref_const<decltype((i))>::type { return i; }
That is, the const needs to go between the type T and the &. The solution would have been obvious if you had put the const into the correct location: const should go to the right.
There's nothing illegal about a const member function modifying the target of a pointer to non-const, even if that pointer was gotten from a member variable.
From the compiler's perspective, int& IS the correct return type.
Your "modify_const" function is incorrectly named. i is what gets modified, and is not const.
Simply add an & to the left and skip the trailing return type.
struct X {
int &i;
X(int &ii) : i(ii) {}
auto& acc() const { return i; } // Returns const reference
auto& acc() { return i; } // Returns non-const reference
const auto& acc() const { return i; } // Add const to the left to make it even more readable
};
Note that using this syntax you can declare the member variable after you have declared the function.
In C++03, Boost's Foreach, using this interesting technique, can detect at run-time whether an expression is an lvalue or an rvalue. (I found that via this StackOverflow question: Rvalues in C++03 )
Here's a demo of this working at run-time
(This is a more basic question that arose while I was thinking about this other recent question of mine. An answer to this might help us answer that other question.)
Now that I've spelled out the question, testing rvalue-ness in C++03 at compile-time, I'll talk a little about the things I've been trying so far.
I want to be able to do this check at compile-time. It's easy in C++11, but I'm curious about C++03.
I'm trying to build upon their idea, but would be open to different approaches also. The basic idea of their technique is to put this code into a macro:
true ? rvalue_probe() : EXPRESSION;
It is 'true' on the left of the ?, and therefore we can be sure that EXPRESSION will never be evaluated. But the interesting thing is that the ?: operator behaves differently depending on whether its parameters are lvalues or rvalues (click that link above for details). In particular, it will convert our rvalue_probe object in one of two ways, depending on whether EXPRESSION is an lvalue or not:
struct rvalue_probe
{
template< class R > operator R () { throw "rvalue"; }
template< class L > operator L & () const { throw "lvalue"; }
template< class L > operator const L & () const { throw "const lvalue"; }
};
That works at runtime because the thrown text can be caught and used to analyze whether the EXPRESSION was an lvalue or an rvalue. But I want some way to identify, at compile-time, which conversion is being used.
Now, this is potentially useful because it means that, instead of asking
Is EXPRESSION an rvalue?
we can ask:
When the compiler is compiling true ? rvalue_probe() : EXPRESSION, which of the two overloaded operators, operator X or operator X&, is selected?
( Ordinarily, you could detect which method was called by changing the return types and getting the sizeof it. But we can't do that with these conversion operators, especially when they're buried inside the ?:. )
I thought I might be able to use something like
is_reference< typeof (true ? rvalue_probe() : EXPRESSION) > :: type
If the EXPRESSION is an lvalue, then the operator& is selected and I hoped that the whole expression would then be a & type. But it doesn't seem to work. ref types and non-ref types are pretty hard (impossible?) to distinguish, especially now that I'm trying to dig inside a ?: expression to see which conversion was selected.
Here's the demo code pasted here:
#include <iostream>
using namespace std;
struct X {
X(){}
};
X x;
X & xr = x;
const X xc;
X foo() { return x; }
const X fooc() { return x; }
X & foor() { return x; }
const X & foorc() { return x; }
struct rvalue_probe
{
template< class R > operator R () { throw "rvalue"; }
// template< class R > operator R const () { throw "const rvalue"; } // doesn't work, don't know why
template< class L > operator L & () const { throw "lvalue"; }
template< class L > operator const L & () const { throw "const lvalue"; }
};
typedef int lvalue_flag[1];
typedef int rvalue_flag[2];
template <typename T> struct isref { static const int value = 0; typedef lvalue_flag type; };
template <typename T> struct isref<T&> { static const int value = 1; typedef rvalue_flag type; };
int main() {
try{ true ? rvalue_probe() : x; } catch (const char * result) { cout << result << endl; } // Y lvalue
try{ true ? rvalue_probe() : xc; } catch (const char * result) { cout << result << endl; } // Y const lvalue
try{ true ? rvalue_probe() : xr; } catch (const char * result) { cout << result << endl; } // Y lvalue
try{ true ? rvalue_probe() : foo(); } catch (const char * result) { cout << result << endl; } // Y rvalue
try{ true ? rvalue_probe() : fooc(); } catch (const char * result) { cout << result << endl; } // Y rvalue
try{ true ? rvalue_probe() : foor(); } catch (const char * result) { cout << result << endl; } // Y lvalue
try{ true ? rvalue_probe() : foorc(); } catch (const char * result) { cout << result << endl; } // Y const lvalue
}
(I had some other code here at the end, but it's just confusing things. You don't really want to see my failed attempts at an answer! The above code demonstrates how it can test lvalue-versus-rvalue at runtime.)
It took some effort, but here's a tested and working is_lvalue macro that correctly handles const struct S function return types. It relies on const struct S rvalues not binding to const volatile struct S&, while const struct S lvalues do.
#include <cassert>
template <typename T>
struct nondeducible
{
typedef T type;
};
char (& is_lvalue_helper(...))[1];
template <typename T>
char (& is_lvalue_helper(T&, typename nondeducible<const volatile T&>::type))[2];
#define is_lvalue(x) (sizeof(is_lvalue_helper((x),(x))) == 2)
struct S
{
int i;
};
template <typename T>
void test_()
{
T a = {0};
T& b = a;
T (* c)() = 0;
T& (* d)() = 0;
assert (is_lvalue(a));
assert (is_lvalue(b));
assert (!is_lvalue(c()));
assert (is_lvalue(d()));
}
template <typename T>
void test()
{
test_<T>();
test_<const T>();
test_<volatile T>();
test_<const volatile T>();
}
int main()
{
test<int>();
test<S>();
}
Edit: unnecessary extra parameter removed, thanks Xeo.
Edit again: As per the comments, this works with GCC but relies on unspecified behaviour in C++03 (it's valid C++11) and fails some other compilers. Extra parameter restored, which makes it work in more cases. const class rvalues give a hard error on some compilers, and give the correct result (false) on others.
The address-of operator (&) can only be used with an lvalue. So if you used it in an SFINAE test, you could distinguish at compile-time.
A static assertion could look like:
#define STATIC_ASSERT_IS_LVALUE(x) ( (sizeof &(x)), (x) )
A trait version might be:
template<typename T>
struct has_lvalue_subscript
{
typedef char yes[1];
typedef char no[2];
yes fn( char (*)[sizeof (&(((T*)0)->operator[](0))] );
no fn(...);
enum { value = sizeof(fn(0)) == 1 };
};
and could be used like
has_lvalue_subscript< std::vector<int> >::value
(Warning: not tested)
I can't think of any way to test an arbitrary expression valid in the caller's context, without breaking compilation on failure.