Consider the following code, which uses a function with variable arguments:
#include <iostream>
// Typedef function type
template<typename... Output>
using Func = void(Output*...);
// Function runner
template<typename... Output>
void run_func(Func<Output...>& func, Output*... output) {
for (int i=0 ; i < 10 ; ++i) {
func(output...);
}
}
void f(double* d) {
*d *= 2;
};
int main() {
double value = 1.0;
run_func(f, &value);
printf("%f\n", value);
}
Compiling this with g++ 4.7.3 works fine, and running produces 1024.0 as expected.
Compiling using icpc 14.0.2 crashes it...
templ.cc(21): internal error: assertion failed: lower_expr: bad kind (shared/cfe/edgcpfe/lower_il.c, line 18582)
run_func(f, &value);
^
Compiling with clang 3.5.0-1 gives the following error message:
templ.cc:21:3: error: no matching function for call to 'run_func'
run_func(f, &value);
^~~~~~~~
templ.cc:9:6: note: candidate template ignored: deduced conflicting types for parameter 'Output' ('double' vs. <double>)
void run_func(Func<Output...>& func, Output*... output) {
^
Is this a bug, or should have g++ not compiled this?
Why is clang deducing these "conflicting" types of double and <double>, is <double> meant to represent an unpacked arglist for example?
Update icpc 14.0.3 does not crash, and the program compiles and runs correctly.
See DPD200244439 at Intel® Composer XE 2013 SP1 Compilers Fixes List
Following the above discussion, it seems that this is indeed a bug in clang.
As pointed out by gha.st, skipping template using and using the native function type directly works:
void run_func(void (&func)(Output*...), Output*... output) {
I have a filed a bug against this here.
Related
In trying to understand c++17 compliant code, i am confused by the following code in
which the function uses the value from integral_constant type argument in the
trailing return type. (please feel free to correct my terminolgy etc, trying to learn)
Two simple versions are illustrated below , with and without a decltype on the
argument in the trailing return.
Using Compiler Explorer https://godbolt.org/z/vqmzhu
The first (bool_from1) compiles ok on
MSVC 15.8; /std:c++17, /O2, /permissive-
and clang 8.7.0.0 and gcc 8.2; -std=c++17, -O2, -pedantic
with correct assembler output
The second (bool_from2) errors out on gcc,
It also shows Intellisense errors in VS but compiles without error.
I could not find anything in cppreference or standard draft, etc that would indicate to me that the decltype(atype) would be required for conforming code, however...???
My question would be is the decltype required.
Are my compiler flags correct for c++17 conformance checking.
CODE:
#include <utility>
namespace ns {
volatile bool vb;
template<bool B> struct bool_ : std::bool_constant<B> {};
// using decltype(btype) in trailing return compiles in all 3
template<typename Bool> constexpr auto bool_from1(Bool btype)
-> bool_<decltype(btype)::value> {
return bool_<btype.value>{};
}
void test1() {
static_assert( // simple test
bool_from1(std::true_type{}).value
);
vb = bool_from1(std::true_type{}).value; // check output
}
// without decltype in trailing return compile in VS and clang
// but errors out in gcc; and VS shows Intelisense errors but compiles
template<typename Bool>
constexpr auto bool_from2(Bool btype)
// ^ gcc 8.2 error: deduced class type 'bool_' in function return type
-> bool_<btype.value> {
// ^ gcc: invalid template-id; use of paramter outside function body before '.'
//^ VS Intellisense on btype: <error-constant>; a paramter is not allowed
return bool_<btype.value>{};
}
void test2() {
static_assert(
bool_from2(std::true_type{}).value
//^ gcc: bool_from1 was not declared in this scope
);
vb = bool_from2(std::true_type{}).value; // check output
}
}
This looks like a gcc bug and bug report: "Trailing return types" with "non-type template arguments" which could be "constant expressions" produce a parsing error seems to fit this case:
Consider the following snippet:
template <int>
struct bar {};
template <class I>
auto foo(I i) -> bar<i()> { return {}; }
int main()
{
foo([]{ return 1; }); // (0)
}
This compiles and works as intended on clang++5, but produces a
compile-time error on g++7:
prog.cc:5:25: error: template argument 1 is invalid
auto foo(I i) -> bar<i()> { return {}; }
Template argument deduction appears to be broken in Clang 6 for temporary objects.
g++ 8.1.0 compiles and runs the example correctly.
Clang 6.0.0 and 6.0.2 both error at the indicated line with this message:
error: expected unqualified-id
Print{1,"foo"s,2}; /********** Broken in Clang **********/
All Other lines work correctly.
The behavior is the same in both cases whether -std=c++17 or -std=c++2a is used.
The Clang c++ Status Page indicates that template argument deduction was implemented as of Clang 5 (P0091R3, P0512R0).
Is this a bug? Are there workarounds (e.g. compiler flags, not code changes)?
example:
template<class ...Ts>
void print(Ts...ts){ (( cout << ... << ts )); }
template<class ...Ts>
struct Print {
Print(Ts...ts){ (( cout << ... << ts )); }
};
int main(){
Print{1,"foo"s,2}; /********** Broken in Clang **********/
Print<int,string,int>{1,"foo"s,2};
auto p1 = Print{1,"foo"s,2};
Print p2{1,"foo"s,2};
print(1,"foo"s,2);
}
This is Clang bug 34091.
Luckily, it is already fixed, and the trunk build of Clang compiles this without issue.
As far as I know, however, there is currently no way to work around this without code changes, short of upgrading to the next Clang release whenever that comes out.
When I try to compile this:
#include <functional>
void f(std::function<void()> f)
{
}
void g()
{
f([](auto&&...){});
}
on gcc 7.3, I get the following error:
[x86-64 gcc 7.3 #1] error: could not convert '<lambda closure object>g()::<lambda(auto:1&&, ...)>{}' from 'g()::<lambda(auto:1&&, ...)>' to 'std::function<void()>'
Can someone explain why this is invalid c++? Or should I submit a bug report? (MSVC 14 accepts and compiles it to what I expect.)
This is a gcc bug. It interprets your lambda as follow:
[](auto&&, ...){}
So there's one argument, followed by C variadic.
If you add a name to your parameter pack, then it works as intended:
[](auto&&... pack){}
#include <iostream>
struct Index {
constexpr operator int() const { return 666; }
};
template <int i> void foo() {
std::cout << i << std::endl;
}
void wrapper(Index index) {
foo<index>();
}
int main() {
Index index;
// foo<index>(); // error: the value of ‘index’ is not usable in a constant expression
wrapper(index);
}
Hello, everyone.
I'm using a constexpr conversion of a variable "index" to an int value, which is substituted to a "foo" templated function.
If I directly call foo<index>() from "main", I get a compiler error.
If the same call is done from the "wrapper", then everything compiles and works fine.
What am I missing there?
Compile command: g++ -std=c++14 main.tex with g++ (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6).
A very similar error was reported here. It was first reported with GCC 4.9.0
In the analysis provided:
This is a GCC bug. It appears to be some sort of confusion in the way GCC handles internal linkage non-type template parameters of pointer type.
It has since been resolved.
NOTE: this question was caused by a bug in clang
In attemping to write a function taking an arbitrary number of intitializer_lists whose types need not match, I've stumbled upon a strange error:
template <typename... Ts>
void function(std::initializer_list<Ts> && ...args){
}
int main() {
function({1,2,3}, {'h', 'w'}, {"hello", "aloha"});
return 0;
}
The string literals cause a problem under clang but not under gcc with -pedantic -Wall -Wextra not warning about any extensions.
clang produces the error:
error: no matching function for call to 'function'
function({1,2,3}, {'h', 'w'}, {"hello", "aloha"});
^~~~~~~~
note: candidate function [with Ts = <int, char, char const[6]>] not
viable: no known conversion from 'const char [6]' to 'char const[6]' for
3rd argument
void function(std::initializer_list<Ts> && ...args){
^
So a few questions:
Is clang wrong for rejecting this or is gcc using an extension to deduce an initializer_list of arrays? Or is it deeper where gcc is just passing bad code?
Is this is the equivalent of passing an initializer_list of initializer_lists which is of course not allowed?
What is the difference between const char[6] and char const[6]?
Details:
clang version 3.4 (http://llvm.org/git/clang.git 9a65f4251fe5548e0b4478d584796ca84a6f5ebc) (http://llvm.org/git/llvm.git 4f67afc3d67d9a68f1b37767c9c2966a775186bd)
Target: x86_64-unknown-linux-gnu
Thread model: posix
gcc (Debian 4.7.2-5) 4.7.2
Debian 7
This is a bug in clang: it fails to perform the required array-to-pointer decay when deducing {"hello", "aloha"} against std::initializer_list<Ts>, but only when Ts is a parameter pack.
This program compiles fine:
#include <initializer_list>
template <typename T>
void function(std::initializer_list<T> il) {
}
int main() {
function({"hello", "aloha", "foobarbaz"});
}
but this program triggers the bug:
#include <initializer_list>
template <typename... T>
void function(std::initializer_list<T>... il) {
}
int main() {
function({"hello", "aloha", "foobarbaz"});
}
Edit: Could not find this bug in the LLVM bugzilla tracker, submitted as bug# 18047.