Visual C++ 2010, rvalue reference bug? - c++

Is it a bug in Visual C++ 2010 or right behaviour?
template<class T>
T f(T const &r)
{
return r;
}
template<class T>
T f(T &&r)
{
static_assert(false, "no way"); //< line # 10
return r;
}
int main()
{
int y = 4;
f(y); //< line # 17
}
I thought, the function f(T &&) should never be called but it's called with T = int &. The output:
main.cpp(10): error C2338: no way
main.cpp(17) : see reference to function template instantiation 'T f(T)' being compiled
with
[
T=int &
]
Update 1 Do you know any C++x0 compiler as a reference? I've tried comeau online test-drive but could not compile r-value reference.
Update 2 Workaround (using SFINAE):
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_reference.hpp>
template<class T>
T f(T &r)
{
return r;
}
template<class T>
typename ::boost::disable_if< ::boost::is_reference<T>, T>::type f(T &&r)
{
static_assert(false, "no way");
return r;
}
int main()
{
int y = 4;
f(y);
// f(5); // generates "no way" error, as expected.
}
Update 3 Some of compilers trigger on static_assert(false, "no way") even if no function template instantiation. Workaround (thanks to #Johannes Schaub - litb)
template<class T> struct false_ { static bool const value = false; };
...
static_assert(false_<T>::value, "no way");
or
static_assert(sizeof(T) == sizeof(T), "no way");

As I understand it (and I may not be completely right; the specification is a bit complicated), the template type deduction rules conspire against you.
The compiler first attempts to substitute all templates (it's not choosing at this point yet—just looking for options) and gets:
T const &r matches int lvalue with T = int, creating f(int const &)
T &&r matches int lvalue with T = int& and int & && reduces to int&, creating f(int &) (there are rules saying this in the spec).
Now it comes to selecting correct overload and the later is better match, because the first differs in cv-qualification and the later does not. That's also the reason why when you remove the const, you get ambiguous overload error—the overloads end up being exactly the same.
Ad Update1: gcc supports many of the C++0x features. You can get native windows build from mingw or use cygwin.
Ad Update2: If you really need separate overloads for rvalue and lvalue, that seems to be the only option. But most templates do the right thing with just any kind of reference, perhaps using std::forward to ensure proper resolution of functions they call depending on whether they got rvalue or lvalue).

Your fix doesn't solve the problem with static_assert firing though. The static_assert(false, ...) will still trigger for compilers that parse templates at definition time (most do).
They will see that any function template instantiation will be ill-formed, and the Standard allows them to issue an error for the template itself then, and most will do so.
For making this work you need to make the expression dependent so that the compiler doesn't know when it parses the template that it will always evaluate to false. For example
template<class> struct false_ { static bool const value = false; };
template<class T>
T f(T &&r)
{
static_assert(false_<T>::value, "no way"); //< line # 10
return r;
}

Related

C++ concept member check type ambiquity with reference

I am learning C++ concepts, and I have an obnoxious problem:
I do not know how to differentiate between member variable being variable of type int and member variable being a int&.
Reason for this is that check I am using is using instance.member syntax and in C++ that returns a reference.
Full example:
#include <iostream>
#include <concepts>
template<typename T>
void print(T t) {
std::cout << "generic" << std::endl;
}
template<typename T>
requires requires(T t){
{t.val} -> std::same_as<int&>;
}
void print(T t) {
std::cout << "special" << std::endl;
}
struct S1{
int bla;
};
struct S2{
int val = 47;
};
int x = 47;
struct S3{
int& val=x;
};
int main()
{
print(4.7);
print(S1{});
print(S2{});
print(S3{});
}
I wish print(S3{}) would be handled by generic case, not the special one.
Note that changing my requires stuff to:
{t.val} -> std::same_as<int>;
makes S2 not match the template so that does not work(like I said I think that member access in C++ returns a reference).
Is there a way to fix this?
The problem here is that expression concept checks use decltype((e)) in the check rather than decltype(e) (the extra parentheses matter).
Because t.val is an lvalue of type int (expressions never have reference type), decltype((t.val)) is int& regardless, as you've discovered.
Instead, you need to explicitly use the single-paren syntax:
template <typename T>
requires requires (T t) {
requires std::same_as<decltype(t.val), int&>;
}
void print(T t) {
std::cout << "special" << std::endl;
}
Or
template <typename T>
requires std::same_as<decltype(T::val), int&>
The solution is:
template <typename T>
requires requires(T t)
{
requires std::is_same_v<decltype(t.val), int>; // or `int &` for references
}
void print(T t)
Clang has a bug that causes {T::val} -> std::same_as<int> to work as well, even though the type of the lhs is said to be determined as if by decltype((...)), which should return int & here.
Note that "member access in C++ returns a reference" is false. It can't be the case because expressions can't have reference types. When you write a function with a reference return type, calling it produces an lvalue of a non-reference type.
decltype will add reference-ness to the expression types depending on value category (& for lvalues, && for xvalues, nothing for prvalues). That's why people often think that expressions can have reference types.
It also has a special rule for variables (as opposed to general expressions), which causes it to return the variable type as written, disregarding the expression type & value category. And apparently t.val counts as a variable for this purpose.

C++ Concepts - Can I have a constraint requiring a function be present in a class?

I have a simple code snippet below, which compiles using:
g++-9 -std=c++2a -fconcepts
This is trying to define a concept that requires the presence of a function. I would expect the output to be "yes" but it's not... Any idea why? Thanks.
#include <iostream>
template <typename T>
concept bool HasFunc1 =
requires(T) {
{ T::func1() } -> int;
};
struct Test
{
int func1()
{
return 5;
}
};
int main()
{
if constexpr (HasFunc1<Test>)
std::cout << "yes\n";
}
You are testing for presence of a static member function. What you want is
template <typename T>
concept bool HasFunc1 =
requires(T t) {
{ t.func1() } -> int;
};
Try calling it yourself:
Test::func1();
prog.cc: In function 'int main()':
prog.cc:19:14: error: cannot call member function 'int Test::func1()' without object
19 | Test::func1();
| ^
Oh, right. func1 should either be a static member function, or you should call it on an instance inside your concept:
template <typename T>
concept bool HasFunc1 =
requires(T t) {
{ t.func1() } -> int;
};
#makogan asked (buried 19 deep in comments): what if func has arguments?
The answer is: for simple cases, manufacture parameters using constructors, or new expression. (Not particularly readable, but way more readable than the probably correct way given below).
template <typename T>
concept HasFunc1 =
requires(T t) {
{ t.func1( int() ) } -> std::same_as<int>;
};
For more complex examples, you can declare test parameters in the requires clause argument list:
concept IsCoServiceImplementation = requires(
T t,
CoServiceReply<typename T::return_type> *completionCallback)
{
{ T::return_type };
{t.OnSuspend(completionCallback) };
{t.OnCancel(completionCallback) };
};
This concept does have the desired intent (for me): it mostly converts nested-10-deep error messages about failures to meet a template contract into almost readable first-level error messages.
There's still a strange disconnect between the required code and the concept. It would be really nice to have tighter constraints on parameter types. And testing const-ness is grimly difficult. Far from the feature I had hope for. :-(
I'm still struggling with c++20 features. I'm open to suggestions as to how to do this better.
(A CoService, in case you're wondering, is an experimental attempt I'm working on to make it easier to marshal coroutine code back onto non-coroutine code with minimum fuss and bother).
One can run the concept check at the compile time.
(The OP's check evaluates only at the run time.)
First, prepare a checker function (technically a templated variable):
template <HasFunc1 h>
constexpr bool HasFunc1_satisfied = true;
Then do the check somewhere.
// The class to be tested
struct Test
{
int func1()
{
return 5;
}
};
// Do the test at the compile time
static_assert(HasFunc1_satisfied< Test >);

Deducing a const l-value reference from a non-const l-value reference in C++ template

Suppose you have the following pair of functions:
void f(const int&) {
// Do something, making a copy of the argument.
}
void f(int&&) {
// Do the same thing, but moving the argument.
}
They are fairly redundant—the only difference between the functions being whether they copy or move their argument. Of course, we can do better by re-writing this as a single template function:
template<typename T>
void g(T&&) {
// Do something, possibly using std::forward to copy or move the argument.
}
This works, and is a commonly used idiom in practice. But the template might be instantiated into three functions, up from our two above. We can verify this occurs with the following piece of code:
#include <iostream>
template<typename T> constexpr char *type = nullptr;
template<> constexpr const char *type<int&> = "int&";
template<> constexpr const char *type<const int&> = "const int&";
template<> constexpr const char *type<int> = "int";
template<typename T>
void g(T&&) {
std::cout << reinterpret_cast<void*>(&g<T>)
<< " = &g<" << type<T> << ">" << std::endl;
}
int main() {
int i = 0;
const int& cr = 0;
g(i);
g(cr);
g(0);
return 0;
}
/*
Prints:
0x100f45080 = &g<int&>
0x100f45100 = &g<const int&>
0x100f45180 = &g<int>
*/
This has added a third function for the case when T = int&, which we didn't have when we were using our non-templated function f above. In this case, we don't actually need this non-const l-value reference version of the function—given f was sufficient for our original needs—and this increases the size of our code, especially if we have many template functions written this way that call each other.
Is there a way to write our function g above so that the compiler will automatically deduce T = const int& when g(i) is called in our example code? I.e., a way where we don't have to manually write g<const int&>(i) yet still get the desired behavior.
It is a subjective point-of-view to say "forward references" ("universal references") are better than dedicated overloads. There are certainly many cases where this is true, but if you want to have full control they won't do all the jobs.
You could explicitly make sure users do not pass non-const lvalue references, by adding
static_assert(!std::is_lvalue_reference<T>::value || std::is_const<typename std::remove_reference<T>::type>::value, "only call g with const argument");
inside g, but this is not in all cases a very good solution.
Or you do what is done for vector::push_back(...) and provide explicit overloads -- but this was your starting point, see https://en.cppreference.com/w/cpp/container/vector/push_back.
The 'correct' answer just depends on your requirements.
Edit:
the suggestion of #Sjoerd would look something like:
template <typename T>
class aBitComplicated {
public:
void func(T&& v) { internal_func(std::forward<T>(v)); }
void func(const T& v) { internal_func(v); }
private:
template <typename U>
void internal_func(U&& v) { /* your universal code*/ }
};
There also a bit more sophisticated/complicated version of this, but this here should be the most simple version to achieve what you asked for.

Why std::is_function<T> is causing compilation error?

Hi I was trying to implement a C++ concept-like feature (C++14) in C++11. The idea is just to write the wrapper function for std::for_each() algorithm where I just check whether the 3rd argument is a function or not. So I wrote the following code, however I am not able to compile it as it should be. I am using Ubuntu12.04 with gcc4.8.1.
test_1.cpp
#include<type_traits>
#include<iostream>
#include<vector>
#include<algorithm>
void display(int& val) {
std::cout <<val<<std::endl;
}
template<typename T>
constexpr bool Is_valid_function(T& a) {
return std::is_function<T>::value;
}
template<typename T>
void check_valid_function(T& a) {
static_assert(Is_valid_function(a), "Not The Valid Function");
}
template <class InputIterator, class Function>
Function my_for_each(InputIterator first, InputIterator last, Function f) {
/* Concept Like Implementation to just check whether f is function or not */
check_valid_function(f);
return for_each(first, last, f) ;
}
void learn_static_assert_and_typetraits(void)
{
std::vector<int> vec_x{1,2,3,4,5};
my_for_each(vec_x.begin(), vec_x.end(), display);
}
int main(int argc, const char* argv[]) {
learn_static_assert_and_typetraits();
return 0;
}
I am getting the following compilation error from which I can see that the static_assert() fails which is not correct as display is valid function.
Compilation Error
test_3.cpp: In instantiation of ‘void check_valid_function(T&) [with T = void (*)(int&)]’:
test_3.cpp:27:26: required from ‘Function my_for_each(InputIterator, InputIterator, Function) [with InputIterator = __gnu_cxx::__normal_iterator >; Function = void (*)(int&)]’
test_3.cpp:35:50: required from here
test_3.cpp:19:3: error: static assertion failed: Not The Valid Function
static_assert(Is_valid_function(a), "Not The Valid Function");
^
However if I do the same thing for the other type_traits function, I am getting the following error which is correct and expected.
test_2.cpp
#include<type_traits>
template<typename T>
constexpr bool Is_floating_point(T& a) {
return std::is_floating_point<T>::value;
}
template<typename T>
void f(T& a) {
static_assert(Is_floating_point(a), "Non-Float Type Data");
}
void learn_static_assert_and_typetraits(void) {
float y{10.0};
f(y);
int x{100};
f(x);
}
int main(int argc, const char* argv[]) {
learn_static_assert_and_typetraits();
return 0;
}
Compiler Output
test_2.cpp: In instantiation of ‘void f(T&) [with T = int]’:
test_2.cpp:19:6: required from here
test_2.cpp:11:3: error: static assertion failed: Non-Float Type Data
static_assert(Is_floating_point(a), "Non-Float Type Data");
^
Question
So, I wanted to understand why my first program is not working as it should be, whether there is bug in my code/understanding or it is something else. I hope the above data would be sufficient to understand my question. However if anyone wants some additional data, please let me know.
The issue is here:
template <class InputIterator, class Function>
Function my_for_each(InputIterator first, InputIterator last, Function f)
invoked via:
my_for_each(vec_x.begin(), vec_x.end(), display);
This deduces Function (of my_for_each) to be a function pointer; for
void display(int& val)
the deduced type is void(*)(int&). The type trait std::is_function however checks if the passed type is a function type, not a function pointer type.
One solution is to remove the pointer:
template<typename T>
constexpr bool Is_valid_function(T& a) {
return std::is_function<typename std::remove_pointer<T>::type>::value;
}
But, as clang++ reveals, this still isn't sufficient:
template<typename T>
void check_valid_function(T& a) {
static_assert(Is_valid_function(a), "Not The Valid Function");
}
a as a function parameter (even if check_valid_function was constexpr!) is not a compile-time constant, therefore it may not appear in a constant expression (inside the function body). Hence, Is_valid_function(a) may not appear as the check for the static_assert. It might be possible to use something similar to declval, e.g.
static_assert(Is_valid_function( declval<T&>() ), "Not The Valid Function");
but unfortunately, declval is not constexpr, and I don't know how to write a constexpr version. So, you could pass a pointer instead:
static_assert(Is_valid_function(static_cast<T*>(nullptr)),
"Not a valid function");
For this, you need to rewrite Is_valid_function as follows:
template<typename T>
constexpr bool Is_valid_function(T*) {
return std::is_function<typename std::remove_pointer<T>::type>::value;
}
Note: the passed argument here is a pointer to a pointer to a function, but the parameter T* deduced T to be a pointer to a function, as before (hence the change in the signature). You might want to reflect that in the function name, if you choose this solution.
Other issues:
Relying on ADL for Standard Library algorithms
return for_each(first, last, f) ;
As far as I can see, this relies on ADL. But the iterators (and the function) are not required to be in namespace std (even for vector::iterator etc.), so you shouldn't rely on ADL:
return std::for_each(first, last, f);
Use of non-const refs for functions that don't need to modify their arguments, e.g.
constexpr bool Is_valid_function(T& a)
If you don't need to modify an argument, you should either pass it by value or by const reference, e.g.
constexpr bool Is_valid_function(T const& a)
"Wrong check" If this code is just for educational purposes, this isn't an issue. However, the check if the passed argument is of a function type is the "wrong check" when trying to check if the argument valid for a Standard Library algorithm. You should rather check whether f(*first) is well-formed. This allows for function objects and checks if the argument type is "valid".

C++11 constexpr function's argument passed in template argument

This used to work some weeks ago:
template <typename T, T t>
T tfunc()
{
return t + 10;
}
template <typename T>
constexpr T func(T t)
{
return tfunc<T, t>();
}
int main()
{
std::cout << func(10) << std::endl;
return 0;
}
But now g++ -std=c++0x says:
main.cpp: In function ‘constexpr T func(T) [with T = int]’:
main.cpp:29:25: instantiated from here
main.cpp:24:24: error: no matching function for call to ‘tfunc()’
main.cpp:24:24: note: candidate is:
main.cpp:16:14: note: template<class T, T t> T tfunc()
main.cpp:25:1: warning: control reaches end of non-void function [-Wreturn-type]
clang++ -std=c++11 says that template's parameters of tfunc<T, t>() are ignored because invalid.
Is that a bug, or a fix ?
PS:
g++ --version => g++ (GCC) 4.6.2 20120120 (prerelease)
clang++ --version => clang version 3.0 (tags/RELEASE_30/final) (3.0.1)
The parameter t is not a constant expression. Hence the error. It should be also noted that it cannot be a constant expression.
You can pass the constant expression as argument, but inside the function, the object (the parameter) which holds the value, is not a constant expression.
Since t is not a constant expression, it cannot be used as template argument:
return tfunc<T, t>(); //the second argument must be a constant expression
Maybe, you want something like this:
template <typename T, T t>
T tfunc()
{
return t + 10;
}
template <typename T, T t> //<---- t became template argument!
constexpr T func()
{
return tfunc<T, t>();
}
#define FUNC(a) func<decltype(a),a>()
int main()
{
std::cout << FUNC(10) << std::endl;
}
Now it should work : online demo
I get the feeling that constexpr must also be valid in a 'runtime' context, not just at compile-time. Marking a function as constexpr encourages the compiler to try to evaluate it at compile-time, but the function must still have a valid run-time implementation.
In practice, this means that the compiler doesn't know how to implement this function at runtime:
template <typename T>
constexpr T func(T t)
{
return tfunc<T, t>();
}
A workaround is to change the constructor such that it takes its t parameter as a normal parameter, not as a template parameter, and mark the constructor as constexpr:
template <typename T>
constexpr T tfunc(T t)
{
return t + 10;
}
template <typename T>
constexpr T func(T t)
{
return tfunc<T>(t);
}
There are three levels of 'constant-expression-ness':
template int parameter, or (non-VLA) array size // Something that must be a constant-expression
constexpr // Something that may be a constant-expression
non-constant-expression
You can't really convert items that are low in that list into something that is high in that list, but obviously the other route it possible.
For example, a call to this function
constexpr int foo(int x) { return x+1; }
isn't necessarily a constant-expression.
// g++-4.6 used in these few lines. ideone doesn't like this code. I don't know why
int array[foo(3)]; // this is OK
int c = getchar();
int array[foo(c)]; // this will not compile (without VLAs)
So the return value from a constexpr function is a constant expression only if all the parameters, and the implementation of the function, can be completed at executed at compile-time.
Recap the question: You have two functions which take a parameter of type T. One takes its parameter as a template parameter, and the other as a 'normal' parameter.
I'm going to call the two functions funcT and funcN instead of tfunc and func.
You wish to be able to call funcT from funcN. Marking the latter as a constexpr doesn't help.
Any function marked as constexpr must be compilable as if the constexpr wasn't there. constexpr functions are a little schizophrenic. They only graduate to full constant-expressions in certain circumstances.
It would not be possible to implement funcN to run at runtime in a simple way, as it would need to be able to work for all possible values of t. This would require the compiler to instantiate many instances of tfunc, one for each value of t. But you can work around this if you're willing to live with a small subset of T. There is a template-recursion limit of 1024 in g++, so you can easily handle 1024 values of T with this code:
#include<iostream>
#include<functional>
#include<array>
using namespace std;
template <typename T, T t>
constexpr T funcT() {
return t + 10;
}
template<typename T, T u>
constexpr T worker (T t) {
return t==0 ? funcT<T,u>() : worker<T, u+1>(t-1);
}
template<>
constexpr int worker<int,1000> (int ) {
return -1;
}
template <typename T>
constexpr T funcN(T t)
{
return t<1000 ? worker<T,0>(t) : -1;
}
int main()
{
std::cout << funcN(10) << std::endl;
array<int, funcN(10)> a; // to verify that funcN(10) returns a constant-expression
return 0;
}
It uses a function worker which will recursively convert the 'normal' parameter t into a template parameter u, which it then uses to instantiate and execute tfunc<T,u>.
The crucial line is return funcT<T,u>() : worker<T, u+1>(t-1);
This has limitations. If you want to use long, or other integral types, you'll have to add another specialization. Obviously, this code only works for t between 0 and 1000 - the exact upper limit is probably compiler-dependent. Another option might be to use a binary search of sorts, with a different worker function for each power of 2:
template<typename T, T u>
constexpr T worker4096 (T t) {
return t>=4096 ? worker2048<T, u+4096>(t-4096) : worker2048<T, u>(t);
}
I think this will work around the template-recursion-limit, but it will still require a very large number of instantiations and would make compilation very slow, if it works at all.
Looks like it should give an error - it has no way of knowing that you passed in a constant value as t to func.
More generally, you can't use runtime values as template arguments. Templates are inherently a compile-time construct.