Why can't clang++ deduce this lambda's return value? - g++

Consider the following function:
#include <utility>
#include <iterator>
#include <algorithm>
template<template<class, class> class Map, typename Key, typename Value , typename F>
auto transform_values(const Map<Key,Value>& map, const F& value_mapper)
{
using mapped_value_type = decltype(value_mapper(std::declval<Value>()));
Map<Key, mapped_value_type> transformed;
std::transform(map.cbegin(), map.cend(), std::inserter(transformed, transformed.begin()),
[&value_mapper](const auto& pair) {
const auto& key = pair.first;
const auto& value = pair.second;
return {key, value_mapper(value)};
}
);
return transformed;
}
g++ 12 accepts this, clang++ 14 does not (GodBolt). clang++ 14 says:
<source>:15:20: error: cannot deduce lambda return type from initializer list
return {key, value_mapper(value)};
^~~~~~~~~~~~~~~~~~~~~~~~~~
Why won't it deduce the lambda's type?

I can't see how the compiler can deduce return type here. The return type of the lambda should be convertible to the type pointed to by the output iterator, but without complete container class it doesn't even know what this type is.
Edit.
For the part what rule makes it fail (i.e. why no valid specialization can be generated), i believe it refers to 9.2.9.6.2 Placeholder type deduction / 2.1.2 rule:
A type T containing a placeholder type, and a corresponding initializer-
clause E, are determined as follows:
For a non-discarded return statement that occurs in a function declared with a return type that contains a placeholder type, T is the declared return type.
...
If the operand is a braced-init-list ([dcl.init.list]), the program is ill-formed.

Related

How to properly check for member at compile time with boost::hana?

I am writing a physics simulation program and I want to do the following:
I have a hana adapted struct and I want to check if this struct has member called "absorbedEnergy" at compile time using:
if constexpr ( ... )
What is the proper way of doing that in c++17 which I use?
Now using hana documentation I have came up with this:
struct HasAE { double absorbedEnergy };
struct HasNoAE {};
temaplate<typename Cell>
void irelevantFunction(Cell& cell){
auto has_absorbedEnergy = hana::is_valid(
[](auto &&p) -> decltype((void) p.absorbedEnergy) {});
if constexpr(has_absorbedEnergy(cell)) { ... }
}
HasAE cell;
HasNoAE anotherCell;
cell.absorbedEnergy = 42; //value known at runtime
irelevantFunction(cell);
irelevantFunction(anotherCell);
The thing is that this compiles just fine with g++ 7.4.0 and does what I expect but fails to compile with clang++-8. It gives an error:
constexpr if condition is not a constant expression
I suspect that this originates from the fact that argument of has_absorbedEnergy - cell is not and constant expression. Is there a way around this?
Your issue seems to be related to the requirement in the standard for the expession in if constexpr to be "contextually converted constant expression of type bool" (see this question). You can work around that by changing the if constexpr to:
if constexpr (decltype(has_absorbedEnergy(cell)){})
https://wandbox.org/permlink/hmMNLberLJmt0ueJ
Alternatively, you can use expression SFINAE to achieve what you want (see the cppreference.com documentation of std::void_t):
#include <type_traits>
#include <iostream>
template <typename, typename= std::void_t<>>
struct has_absorbedEnergy : std::false_type {};
template <typename T>
struct has_absorbedEnergy<T,
std::void_t<decltype(std::declval<T&>().absorbedEnergy)>>
: std::true_type {};
template <typename Cell>
void irelevantFunction([[maybe_unused]] Cell &cell) {
if constexpr (has_absorbedEnergy<Cell>::value)
std::cout << "Has absorbedEnergy\n";
else
std::cout << "Does not have absorbedEnergy\n";
}
struct HasAbsorbedEnergy
{ int absorbedEnergy; };
struct DoesNotHaveAbsorbedEnergy
{};
int main()
{
HasAbsorbedEnergy Has;
DoesNotHaveAbsorbedEnergy DoesNot;
irelevantFunction(Has);
irelevantFunction(DoesNot);
}
https://wandbox.org/permlink/0559JhpVQBOwHC0Z

How to fill an xtensor array, with complex data type

Paraphrasing here, but this is the problem
xt::pyarray< std::complex<double> > output;
output = 0; // fails to compile
output = double(0); // also fails to compile
output = complex<double>(0); // succeeds
and yet this is fine
std::complex<double> foo;
foo = double(0);
The problem is I'm writing a function which accepts arbitrary xtensor array, eg.
template<typename xtarray_t>
void my_function(xtarray_t &output, const xtarray_t &input) {
output = 0;
}
so in general this
output = complex<double>(0);
would fail. I've seen this, but am not sure if this was implemented, or how to use it, couldn't find the documentation. In general though, I think it should still work with std::complex.
thanks for any help!
compiler output:
xtensor-python/include/xtensor-python/pyarray.hpp:360:20: note: candidate function not viable: no known conversion from 'double' to 'const xt::pyarray<std::__1::complex<double>, xt::layout_type::dynamic>::self_type' (aka 'const pyarray<std::__1::complex<double>, (xt::layout_type)0>') for 1st argument
self_type& operator=(const self_type& rhs);
xtensor-python/include/xtensor-python/pyarray.hpp:363:20: note: candidate function not viable: no known conversion from 'double' to 'xt::pyarray<std::__1::complex<double>, xt::layout_type::dynamic>::self_type' (aka 'pyarray<std::__1::complex<double>, (xt::layout_type)0>') for 1st argument
self_type& operator=(self_type&& e) = default;
xtensor-python/include/xtensor-python/pyarray.hpp:369:20: note: candidate template ignored: could not match 'xexpression<type-parameter-0-0>' against 'double'
self_type& operator=(const xexpression<E>& e);
Answer is to do this
using value_t = typename xtarray_t::value_type;
output = value_t(0);

Structure of a block declaration

When declaring a block what's the rationale behind using this syntax (i.e. surrounding brackets and caret on the left)?
(^myBlock)
For example:
int (^myBlock)(int) = ^(int num) {
return num * multiplier;
};
C BLOCKS: Syntax and Usage
Variables pointing to blocks take on the exact same syntax as variables pointing to functions, except * is substituted for ^. For example, this is a function pointer to a function taking an int and returning a float:
float (*myfuncptr)(int);
and this is a block pointer to a block taking an int and returning a float:
float (^myblockptr)(int);
As with function pointers, you'll likely want to typedef those types, as it can get relatively hairy otherwise. For example, a pointer to a block returning a block taking a block would be something like void (^(^myblockptr)(void (^)()))();, which is nigh impossible to read. A simple typedef later, and it's much simpler:
typedef void (^Block)();
Block (^myblockptr)(Block);
Declaring blocks themselves is where we get into the unknown, as it doesn't really look like C, although they resemble function declarations. Let's start with the basics:
myvar1 = ^ returntype (type arg1, type arg2, and so on) {
block contents;
like in a function;
return returnvalue;
};
This defines a block literal (from after = to and including }), explicitly mentions its return type, an argument list, the block body, a return statement, and assigns this literal to the variable myvar1.
A literal is a value that can be built at compile-time. An integer literal (The 3 in int a = 3;) and a string literal (The "foobar" in const char *b = "foobar";) are other examples of literals. The fact that a block declaration is a literal is important later when we get into memory management.
Finding a return statement in a block like this is vexing to some. Does it return from the enclosing function, you may ask? No, it returns a value that can be used by the caller of the block. See 'Calling blocks'. Note: If the block has multiple return statements, they must return the same type.
Finally, some parts of a block declaration are optional. These are:
The argument list. If the block takes no arguments, the argument list can be skipped entirely.
Examples:
myblock1 = ^ int (void) { return 3; }; // may be written as:
myblock2 = ^ int { return 3; }
The return type. If the block has no return statement, void is assumed. If the block has a return statement, the return type is inferred from it. This means you can almost always just skip the return type from the declaration, except in cases where it might be ambiguous.
Examples:
myblock3 = ^ void { printf("Hello.\n"); }; // may be written as:
myblock4 = ^ { printf("Hello.\n"); };
// Both succeed ONLY if myblock5 and myblock6 are of type int(^)(void)
myblock5 = ^ int { return 3; }; // can be written as:
myblock6 = ^ { return 3; };
source: http://thirdcog.eu/pwcblocks/
I think the rationale is that it looks like a function pointer:
void (*foo)(int);
Which should be familiar to any C programmer.

Trouble with block, iOS

I get this error when trying to define and assign a block:
int (^bl)(int) = ^(int k)
{
[_self c2:k]; // incompatible block pointer types initializing 'int (^)(int)' with an expression of type 'void (^)(int)'
};
This is from a blocks tutorial:
What is going on?
Change the return type of bl from int to void.
void (^bl)(int) = ^(int k) {
[_self c2:k];
};
If you look at the language specification for blocks you will see what's going on:
The return type is optional and is inferred from the return statements. If the return statements return a value, they all must return a value of the same type. If there is no value returned the inferred type of the Block is void; otherwise it is the type of the return statement value.
In Apples example case the return type will be the type of num * multiplier which is int matching the return type of the block variable myBlock.
But in your case there is no return statements so the return type will be void which does not match the return type of the block variable bl.

Enumerators Cast

I have en error when try to cast own enumerator to address book values:
typedef enum {
kACTextFirstName = kABPersonFirstNameProperty, // error: expression is not an integer constant expression
kACTextLastName = (int)kABPersonLastNameProperty, // error: expression is not an integer constant expression
} ACFieldType;
How to solve the problem?
Thank you.
I need to init my enum using ABAddressBook's framework const values such as kABPersonLastNameProperty or kABPersonFirstNameProperty.
In C (unlike in C++), an object declared const, even if it's initialized with a constant expression, cannot be used as a constant.
You didn't bother to show us the declaration of kABPersonFirstNameProperty, but I"m guessing it's declared something like:
const int kABPersonFirstNameProperty = 42;
If you need to use the name kABPersonFirstNameProperty as a constant expression, you can either declare it as a macro:
#define kABPersonFirstNameProperty 42
or as an enumeration constant:
enum { kABPersonFirstNameProperty = 42 };
Note that the enum hack only lets you declare constants of type int.
Likewise for kABPersonLastNameProperty.
(And why do you cast one of them to int, but not the other?)
If that doesn't answer your question, it's because you didn't give us enough information.