Variadic template not compiled [duplicate] - c++

This question already has answers here:
Cannot have typeof(std::endl) as template parameter?
(2 answers)
Closed 9 years ago.
Code:
#include <iostream>
template<typename T>
void out() // line 4
{
}
template<typename T, typename... Args>
void out(T value, Args... args) // line 9
{
std::cout << value;
out(args...); // line 12
}
int main()
{
out("12345", std::endl); // line 17
return 0;
}
Build errors:
g++ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++11 -pthread -MMD -MP -MF"main.d" -MT"main.d" -o "main.o" "../main.cpp"
../main.cpp: In function ‘int main()’:
../main.cpp:17:24: error: no matching function for call to ‘out(const char [6], <unresolved overloaded function type>)’
../main.cpp:17:24: note: candidates are:
../main.cpp:4:6: note: template<class T> void out()
../main.cpp:4:6: note: template argument deduction/substitution failed:
../main.cpp:17:24: note: candidate expects 0 arguments, 2 provided
../main.cpp:9:6: note: void out(T, Args ...) [with T = const char*; Args = {}]
../main.cpp:9:6: note: candidate expects 1 argument, 2 provided
I want this program to give the same result as std::cout << "12345" << std::endl; What is wrong in the template function?

The problem is that you made your no argument version of out be a template, and it cannot be called without explicitly supplying template arguments. Thus
void out() {}
template<typename T, typename... Args>
void out(T value, Args... args) {
std::cout << value;
out(args...);
}
int main() {
out(1, 2.0, "3");
return 0;
}
works as intended.

There is a syntax error (a missning .) that makes the compiler go crazy.
After that, you may also have a problem with the out("12345", std::endl) call, being std::endl an overridden function that compiler cannot choose from (just cast it as static_cast<std::ostream&(*)(std::ostream&)>(std::endl))
Also, the recursion in out ends in a out() call, but there is no out with 0 parameters.(see also yuri answer: https://stackoverflow.com/a/20879525/924727 )

Related

Expand template parameter pack to non-type template argument [duplicate]

This question already has answers here:
C-Style Strings as template arguments? [duplicate]
(8 answers)
Passing a string literal as a type argument to a class template
(17 answers)
Closed 1 year ago.
I want to do something on strings in the compile-time, so I wrote a class with non-type parameters. Detail is below.
This is my code, compiled by Clang 11.0.1, C++20
#include <type_traits>
// my non-type template parameters string class
template<char... str>
struct StaticString
{
static constexpr char data[] = { str... };
};
// I will do something in this function, but now just return the character.
template<std::size_t N>
constexpr char nthChar(const char (&str)[N], std::size_t i) { return str[i]; }
// success to compile
inline constexpr char testNthChar = nthChar("xxx", 2);
template<std::size_t N, std::size_t... i>
constexpr auto makeStaticString(const char (&str)[N], std::index_sequence<i...>)
{
return StaticString<nthChar(str, i)...>{};
// ^~~~~~~~~~~~~~~
// error: non-type template argument is not a constant expression
// I tend to think that I made a mistake...
}
template<std::size_t N>
constexpr auto buildStr(const char(&str)[N])
{
// make an index sequence that is used to provide an index to get chars in str
return makeStaticString(str, std::make_index_sequence<N>{}).data;
}
extern const char sf[] = "1234";
void foo()
{
constexpr auto ss = buildStr("0123");
// not caused by internal linkage attribute
// constexpr auto ssExtern = buildStr(sf);
}
The full compiler error:
[build] D:\LLVM\bin\clang++.exe -g -Xclang -gcodeview -O0 -D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd -std=gnu++20 -MD -MT CMakeFiles/test.dir/test.cpp.obj -MF CMakeFiles\test.dir\test.cpp.obj.d -o CMakeFiles/test.dir/test.cpp.obj -c ../test.cpp
[build] ../test.cpp:21:22: error: non-type template argument is not a constant expression
[build] return StaticString<nthChar(str, i)...>{};
[build] ^~~~~~~~~~~~~~~
[build] ../test.cpp:27:9: note: in instantiation of function template specialization 'makeStaticString<4, 0>' requested here
[build] return makeStaticString(str, std::make_index_sequence<1>{}).data;
[build] ^
[build] ../test.cpp:33:22: note: in instantiation of function template specialization 'buildStr<4>' requested here
[build] constexpr auto ss = buildStr("123");
[build] ^
[build] ../test.cpp:21:30: note: function parameter 'str' with unknown value cannot be used in a constant expression
[build] return StaticString<nthChar(str, i)...>{};
[build] ^
[build] 1 error generated.
So my question is, possible to expand the template parameters pack to non-type template arguments, or what is the mistake I made?
I would appreciate your help!

std::endl and variadic template [duplicate]

This question already has answers here:
Cannot have typeof(std::endl) as template parameter?
(2 answers)
Closed 9 years ago.
Code:
#include <iostream>
void out()
{
}
template<typename T, typename... Args>
void out(T value, Args... args)
{
std::cout << value;
out(args...);
}
int main()
{
out("12345", " ", 5, "\n"); // OK
out(std::endl); // compilation error
return 0;
}
Build errors:
g++ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++11 -pthread -MMD -MP -MF"main.d" -MT"main.d" -o "main.o" "../main.cpp"
../main.cpp: In function ‘int main()’:
../main.cpp:17:15: error: no matching function for call to ‘out(<unresolved overloaded function type>)’
../main.cpp:17:15: note: candidates are:
../main.cpp:3:6: note: void out()
../main.cpp:3:6: note: candidate expects 0 arguments, 1 provided
../main.cpp:8:6: note: template<class T, class ... Args> void out(T, Args ...)
../main.cpp:8:6: note: template argument deduction/substitution failed:
../main.cpp:17:15: note: couldn't deduce template parameter ‘T’
So, everything is OK except std::endl. How can I fix this (except of using "\n")?
std::endl is an overloaded function, (in many STL implementations, a template) and the compiler has no info about what to choose from.
Just cast it as static_cast<std::ostream&(*)(std::ostream&)>(std::endl)

Error passing arguments to template function with const qualifier

I have this code example:
#include <iostream>
#include <memory>
template <typename T>
void func1(T& value)
{
std::cout << "passed 1 ..." << std::endl;
}
template <template <typename> class T, typename U>
void func2(T<U>& value)
{
std::cout << "passed 2 ..." << std::endl;
}
int main()
{
std::auto_ptr<int> a;
const std::auto_ptr<int> ca;
// case 1: using func1
func1(a); // OK
func1(ca); // OK
// case 2: using func2
func2(a); // OK
func2(ca); // Compilation error
return 0;
}
In the first case the function 'func1' accepts a generic argument regardless of the qualifier, however the second case the function 'func2' fails when the argument has the const qualifier. Why this happens ?
This is the compilation error:
make all
Building file: ../src/Test2.cpp
Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/Test2.d" -MT"src/Test2.d" -o "src/Test2.o" "../src/Test2.cpp"
../src/Test2.cpp: In function ‘int main()’:
../src/Test2.cpp:27: error: invalid initialization of reference of type ‘std::auto_ptr<int>&’ from expression of type ‘const std::auto_ptr<int>’
../src/Test2.cpp:11: error: in passing argument 1 of ‘void func2(T<U>&) [with T = std::auto_ptr, U = int]’
make: *** [src/Test2.o] Error 1
The problem is that in the case of func1, the compiler needs to deduce T and we get
T is std::auto_ptr<int> in the first call
T is const std::auto_ptr<int> in the second call
In both cases T is valid in itself.
Now for func2, the compiler needs to deduce T and U, where T is a template template parameter. What would be needed is:
T is std::auto_ptr, U is int in the first call
T is const std::auto_ptr, U is int in the second call
and there's your problem: T can not be const std::auto_ptr itself, as it combined a type-property const with a template std::auto_ptr which is not a valid type.

std::function in template function

I was trying to write a template function which can accept functor as parameter and call it afterwards. The program is as follows:
#include <iostream>
#include <functional>
using namespace std;
template<typename R, typename... Args>
R call(function<R(Args...)> fun, Args... args)
{
cout << "call# " << __LINE__ <<endl;
return fun(args...);
}
int main()
{
cout << call(std::plus<int>(),1,2) <<endl;
return 0;
}
The G++ compplains:
g++ -c -Wall -std=c++0x -I../include a.cpp -o a.o
a.cpp: In function ‘int main()’:
a.cpp:16:38: error: no matching function for call to ‘call(std::plus<int>, int, int)’
a.cpp:16:38: note: candidate is:
a.cpp:7:3: note: template<class R, class ... Args> R call(std::function<_Res(_ArgTypes ...)>, Args ...)
a.cpp:7:3: note: template argument deduction/substitution failed:
a.cpp:16:38: note: ‘std::plus<int>’ is not derived from ‘std::function<_Res(_ArgTypes ...)>’
make: *** [a.o] Error 1
I suppose std::plus<int>() could be deduced to std::function<int(int,int)>, but it didn't. Why was that? GCC is gcc version 4.7.2 20120921 (Red Hat 4.7.2-2) (GCC)
I suppose std::plus() could be deduced to std::function
No. It could not be deduced given that you have passed an object of type std::plus<int>.
In your case, you do not need to use std::function, as generally you would mostly use it when storing different functions/function objects that can be called with a specific signature.
With that, you can just have your call function accept the function/function object directly, with its original type deduced, without using std::function. Also, you might also want to use perfect forwarding when accepting the parameters and use std::forward when passing them as arguments to the function/function object. You should also use the return type of your function as the return type of call. Use C++11's trailing return type with decltype for that.
#include <iostream>
#include <functional>
using namespace std;
template<typename R, typename... Args>
auto call(R fun, Args&&... args) -> decltype(fun(std::forward<Args>(args)...))
{
cout << "call# " << __LINE__ <<endl;
return fun(std::forward<Args>(args)...);
}
int main()
{
cout << call(std::plus<int>(),1,2) <<endl;
return 0;
}
LIVE CODE
As what #Jan Hudec has commented, __LINE__ in there will always result the same in all calls to call, whatever function is passed.
It can't deduce the template arguments.
I would recommend changing the function signature like so:
template<typename F, typename... Args>
auto call(F fun, Args... args )
-> decltype( fun(args...) )
Most implicit conversions are not considered when deducing template arguments. Certainly not user-defined ones. So even if plus is convertible to function, it doesn't make a difference.

Non standard code, or g++ error?

Okay I've developed some code;
Linkage (it's rather long)
And when I compile it with Clang++ 3.2, it runs and results in;
stdout:
print: C-3PO
print: R2D2
However if I try to compile it with G++ 4.7.2, I get these errors;
Compilation finished with errors:
source.cpp: In function 'int main()':
source.cpp:90:71: error: no matching function for call to 'makeRunnable(int (&)(char, int, const char*), char, int)'
source.cpp:90:71: note: candidate is:
source.cpp:74:27: note: template<class ... RUN_TIME, class T, class ... CONSTRUCTION_TIME> Runnable<T, RUN_TIME ...>* makeRunnable(T (*)(CONSTRUCTION_TIME ..., RUN_TIME ...), CONSTRUCTION_TIME ...)
source.cpp:74:27: note: template argument deduction/substitution failed:
source.cpp:90:71: note: mismatched types 'const char*' and 'char'
source.cpp:90:71: error: unable to deduce 'auto' from '<expression error>'
source.cpp:92:72: error: no matching function for call to 'makeRunnable(int (&)(char, int, const char*), char)'
source.cpp:92:72: note: candidate is:
source.cpp:74:27: note: template<class ... RUN_TIME, class T, class ... CONSTRUCTION_TIME> Runnable<T, RUN_TIME ...>* makeRunnable(T (*)(CONSTRUCTION_TIME ..., RUN_TIME ...), CONSTRUCTION_TIME ...)
source.cpp:74:27: note: template argument deduction/substitution failed:
source.cpp:92:72: note: mismatched types 'int' and 'char'
source.cpp:92:72: error: unable to deduce 'auto' from '<expression error>'
And almost the same with G++ 4.8.0 (although prettier formatted).
So the question is;
Is this code standard conformant? - If not why?
Edit Relevant code from link:
template<typename... RUN_TIME, typename T, typename... CONSTRUCTION_TIME>
Runnable<T, RUN_TIME...>* makeRunnable(T (*FunctionType)(CONSTRUCTION_TIME..., RUN_TIME...), CONSTRUCTION_TIME... ct_args) // Line 74
{
return new FunctionDelegate<T,
std::tuple<CONSTRUCTION_TIME...>,
std::tuple<CONSTRUCTION_TIME..., RUN_TIME...>,
RUN_TIME...>(FunctionType, std::make_tuple(ct_args...));
}
int print_function(char arg1, int arg2, const char* arg3)
{
std::cout << "print: " << arg1 << arg2 << arg3 << std::endl;
return 2;
}
int main()
{
auto function1 = makeRunnable<const char*>(print_function, 'C', -3); // Line 90
int n = function1->invoke("PO");
auto function2 = makeRunnable<int, const char*>(print_function, 'R'); // Line 92
function2->invoke(n, "D2");
}
The point of this question, isn't really the implementation in question, more that Clang++ and G++ is not disagreeing on whether this is an error or not.
Having played with the code a bit, it seems that g++ can't handle the deducing of variadic template concatenation (between the |!|).
Runnable<T, RUN_TIME...>* makeRunnable(T (*FunctionType)|!|(CONSTRUCTION_TIME..., RUN_TIME...)|!|, CONSTRUCTION_TIME... ct_args)
And the code is fixable, by adding another variadic template argument, such that g++ can deduce the template directly.