VS2010 SFINAE and function overload error - visual-c++

I have code like this, that compiles fines in all compiler I've tested except VS2010.
I'm trying not to use C++11 specific features here, so it can still compile on outdated compiler like gcc 4.1.
#include <iostream>
using namespace std;
// Simplified variant class
struct Var
{
template <class T>
Var(T t) {}
Var(void) {}
};
// Simplified argument array class
struct FuncArgs
{
};
/** Make a wrapper around the given function */
template <int line, typename Ret, Ret Func()>
Var WrapFuncT(const FuncArgs & args)
{
Var ret;
ret = Func(); return ret;
}
/** Make a wrapper around the given function */
template <int line, void Func()>
Var WrapFuncT(const FuncArgs & args)
{
Var ret;
Func(); return ret;
}
// Unary
template <int line, typename Ret, typename Arg1, Ret Func(Arg1)>
Var WrapFuncT(const FuncArgs & args)
{
Var ret; Arg1 arg;
ret = Func(arg);
return ret;
}
template <int line, typename Arg1, void Func(Arg1)>
Var WrapFuncT(const FuncArgs & args)
{
Var ret; Arg1 arg;
Func(arg);
return ret;
}
// Binary
template <int line, typename Ret, typename Arg1, typename Arg2, Ret Func(Arg1, Arg2)>
Var WrapFuncT(const FuncArgs & args)
{
Var ret; Arg1 arg1; Arg2 arg2;
ret = Func(arg1, arg2);
return ret;
}
template <int line, typename Arg1, typename Arg2, void Func(Arg1, Arg2)>
Var WrapFuncT(const FuncArgs & args)
{
Var ret; Arg1 arg1; Arg2 arg2;
Func(arg1, arg2);
return ret;
}
#define WrapFunc(X, Y, ...) &WrapFuncT<__LINE__, X, Y, ## __VA_ARGS__ >
int testFunc()
{
return 42;
}
void testFunc2(int value)
{
cout<<value<<endl;
}
typedef Var (*NamedFunc)(const FuncArgs &);
int main()
{
NamedFunc a, b;
a = WrapFunc(int, testFunc);
b = WrapFunc(int, testFunc2);
}
Visual studio 2010 compiler chokes on this with error:
In line 'a = WrapFunc(int, testFunc);' : error C2440: 'specialization' : cannot convert from 'int (__cdecl *)(void)' to 'void (__cdecl *const )(int)'
This conversion requires a reinterpret_cast, a C-style cast or function-style cast
error C2973: 'Type::WrapFuncT' : invalid template argument 'int (__cdecl *)(void)'
In line 'template <int line, typename Arg1, void Func(Arg1)>' : see declaration of 'Type::WrapFuncT'
Seems like VS2010 does not find the former definition template < int line, typename Ret, Ret Func(void) > with Ret = int for int testFunc(void) function, and instead tries and errors on the template < int line, typename Arg1, void Func(Arg1) >.
If I comment the later, then it compiles fine, so it is able to find the former overload.
I've tried to solve this in numerous way, none worked, as I need to "capture" a pointer to function in a same signature function Var (*) (const FuncArgs &)

You may try a generic template function and using specialization with structure, something like:
namespace detail
{
// class to specialize for each function type
template <int line, typename F, F f> struct helper_wrapper;
// partial specialization
template <int line, typename Ret, Ret (&Func)()>
struct helper_wrapper<line, Ret (&)(void), Func>
{
Var operator()(const FuncArgs&) const
{
Var ret;
ret = Func();
return ret;
}
};
// partial specialization
template <int line, void (&Func)()>
struct helper_wrapper<line, void (&)(), Func>
{
Var operator()(const FuncArgs&) const
{
Var ret;
Func();
return ret;
}
};
// partial specialization
template <int line, typename Ret, typename Arg1, Ret (&Func)(Arg1)>
struct helper_wrapper<line, Ret (&)(Arg1), Func>
{
Var operator()(const FuncArgs&) const
{
Var ret;
Arg1 arg;
ret = Func(arg);
return ret;
}
};
// partial specialization
template <int line, typename Arg1, void (&Func)(Arg1)>
struct helper_wrapper<line, void (&)(Arg1), Func>
{
Var operator()(const FuncArgs&) const
{
Var ret;
Arg1 arg;
Func(arg);
return ret;
}
};
// other partial specialization omitted.
}
// The general function
template <int line, typename F, F f>
Var WrapFuncT(const FuncArgs& arg) { return detail::helper_wrapper<line, F, f>()(arg); }
// The helper macro
#define WrapFunc(X, Y) &WrapFuncT<__LINE__, X, Y>
And then call it that way:
a = WrapFunc(int(&)(), testFunc);
b = WrapFunc(void(&)(int), testFunc2);

Related

Wrong result while using _addcarry_u64 on MSVC 2017

I am trying to write a simple library to work with long integers. Using of special optimization based on intrinsic method _addcarry_u64 of 64-bit compiler get an unexpected result in the following code if used optimization. Debug version working as expected.
inline uint64_t addc(const uint64_t& value1, const uint64_t& value2, uint64_t& carry) noexcept
{
uint64_t result;
carry = _addcarry_u64(static_cast<uint8_t>(carry), value1, value2, &result);
return result;
}
template<typename native_t = uintmax_t>
class long_t
{
public:
static_assert(std::is_unsigned_v<native_t>, "unsigned long integer native type must be unsigned");
using native_array_t = std::array<native_t, 2>;
long_t() noexcept;
constexpr long_t(const long_t& that) noexcept = default;
constexpr long_t(long_t&& that) noexcept = default;
constexpr long_t(native_array_t digits) noexcept;
constexpr long_t(const native_t& value) noexcept;
template<typename type_t, std::enable_if_t<std::is_unsigned_v<type_t>, int> = 0>
constexpr long_t(type_t value) noexcept;
template<typename type_t, std::enable_if_t<std::is_signed_v<type_t>, int> = 0>
constexpr long_t(type_t value) noexcept;
constexpr bool operator==(const long_t& that) const noexcept;
constexpr long_t& operator+=(const long_t& that) noexcept;
constexpr long_t operator+(const long_t& that) const noexcept;
native_array_t digits;
};
template<typename native_t>
inline long_t<native_t>::long_t() noexcept
{
}
template<typename native_t>
inline constexpr long_t<native_t>::long_t(native_array_t digits) noexcept
: digits(digits)
{
}
template<typename native_t>
inline constexpr long_t<native_t>::long_t(const native_t& value) noexcept
: long_t({ value, 0})
{
}
template<typename native_t>
template<typename type_t, std::enable_if_t<std::is_unsigned_v<type_t>, int>>
inline constexpr long_t<native_t>::long_t(type_t value) noexcept
: long_t({ native_t(value), 0 })
{
}
template<typename native_t>
template<typename type_t, std::enable_if_t<std::is_signed_v<type_t>, int>>
inline constexpr long_t<native_t>::long_t(type_t value) noexcept
: long_t({ static_cast<native_t>(value), (value >= 0 ? 0 : native_t(~0)) })
{
}
template<typename native_t>
inline constexpr bool long_t<native_t>::operator==(const long_t& that) const noexcept
{
if (digits[1] != that.digits[1])
return false;
if (digits[0] != that.digits[0])
return false;
return true;
}
template<typename native_t>
inline constexpr long_t<native_t>& long_t<native_t>::operator+=(const long_t& that) noexcept
{
native_t carry = 0;
digits[0] = addc(digits[0], that.digits[0], carry);
digits[1] = addc(digits[1], that.digits[1], carry);
return *this;
}
template<typename native_t>
inline constexpr long_t<native_t> long_t<native_t>::operator+(const long_t& that) const noexcept
{
return long_t(*this) += that;
}
int main()
{
const bool result = long_t<uintmax_t>(0) + -1 == -1;
std::cout << "result:" << result;
return 0;
}
Output is:
result:0
Replacing of optimized addc version caused to predictable result:
template<typename type_t, std::enable_if_t<std::is_unsigned_v<type_t>, int>>
inline constexpr type_t addc(const type_t& value1, const type_t& value2, type_t& carry) noexcept
{
const type_t tmp = value2 + carry;
const type_t result = value1 + tmp;
carry = (tmp < value2) || (result < value1);
return result;
}
Output is:
result:1
The problem appears on Microsoft Visual Studio 2017 version 15.9.23 on 64-bit C++ compiler in full optimization mode.

function template specialization for variadic templated function (printf)

I have some Arduino C++11 code that I'm trying to improve: trying to make a printf-like function treat String specially so I don't have to call c_str() myself everywhere I use it. Basically for any builtin type like int float bool etc, I just want to pass the arg as-is, and for String, pass return the c_str(). Hit some snags so I tried this in some of the online compilers available. Starting point is this, using std::string instead of String:
#include <string>
class SerialOut {
public:
template<class ...Ts>
static void error(const char* msg, Ts... args) {
printf(msg, args...);
}
};
int main() {
std::string greeting("hi");
SerialOut::error("Message %d %s\n", 1, greeting.c_str());
}
So I tried creating a function template that just returns the value it gets, with a specialization for std::string:
#include <string>
template <typename T, typename R=T> R raw(T& x) {return x;}
template <> const char* raw<>(std::string& x) {return x.c_str();}
class SerialOut {
public:
template<class ...Ts>
static void error(const char* msg, Ts... args) {
printf(msg, raw(args)...);
}
};
int main() {
std::string greeting("hi");
SerialOut::error("Message %d %s\n", 1, greeting);
}
I get a compilation error when I run this in https://repl.it/languages/cpp11:
clang version 7.0.0-3~ubuntu0.18.04.1 (tags/RELEASE_700/final)
 clang++-7 -pthread -std=c++11 -o main main.cpp
main.cpp:10:25: error: cannot pass object of non-trivial type
'std::__cxx11::basic_string<char>' through variadic function; call will abort at
runtime [-Wnon-pod-varargs]
printf(msg, raw(args)...);
^
main.cpp:16:20: note: in instantiation of function template specialization
'SerialOut::error<int, std::__cxx11::basic_string<char> >' requested here
SerialOut::error("Message %d %s\n", 1, greeting);
^
1 error generated.
compiler exit status 1
With https://www.onlinegdb.com/online_c++_compiler there is no error but the raw() specialization is not selected, so the output for greeting is garbage.
In Arduino IDE I get a slightly different error (after replacing std::string by String, of course):
sketch\mqtt.cpp.o: In function `char const* raw<String, char const*>(String&)':
sketch/utils.h:15: multiple definition of `char const* raw<String, char const*>(String&)'
sketch\Thermistor.cpp.o:sketch/utils.h:15: first defined here
sketch\sketch.ino.cpp.o: In function `char const* raw<String, char const*>(String&)':
sketch/utils.h:15: multiple definition of `char const* raw<String, char const*>(String&)'
sketch\Thermistor.cpp.o:sketch/utils.h:15: first defined here
I tried several variations on the raw() functions, to no avail. I figure I'm just missing a subtlety or it's just not possible to do this in C++11.
Update: I found Variadic Macro: cannot pass objects of non-trivially-copyable type through '...', one of the answers solves the above in C++14 (basically use decltype(auto) and overload instead of specialization). I added a slight variation on it that works also in C++11, and with "inline" it also works in Arduino C++ (without "inline" on the overload, the above message about multiple definitions -- turns out this is a linker message so it does compile, I guess the Arduino variant doesn't inline "obviously inlined" functions as other compilers).
Something along these lines, perhaps:
template <typename T>
struct SerialHelper {
static T raw(T val) { return val; }
};
template <>
struct SerialHelper<std::string> {
static const char* raw(const std::string& val) { return val.c_str(); }
};
class SerialOut {
public:
template<class ...Ts>
static void error(const char* msg, Ts... args) {
printf(msg, SerialHelper<Ts>::raw(args)...);
}
};
Demo
Based on Variadic Macro: cannot pass objects of non-trivially-copyable type through '...' I got it to work with this very simple change, which works in C++11 and Arduino C++:
#include <string>
template <typename T> T raw(const T& x) {return x;}
inline const char* raw(const String& x) {return x.c_str();}
class SerialOut {
public:
template<class ...Ts>
static void error(const char* msg, Ts... args) {
printf(msg, raw(args)...);
}
};
int main() {
std::string greeting("hi");
SerialOut::error("Message %d %s\n", 1, greeting);
}
Thanks to #IgorTandetnik comment, it is clear why.

operator< for user defined key of map - C2679

I'm trying to create a map like
std::map<std::map <std::string,std::string>, MyDataTyp*>,
therefore I put
std::map<std::string, std::string>
in a separate class like:
class TagList {
public:
std::map<std::string, std::string> _map;
TagList() {}
~TagList() {}
void addTag(const std::string tag, const std::string value) { if (tag != "") _map[tag] = value; }
std::string getValue(const std::string tag) {
std::map<std::string, std::string>::iterator it = _map.find(tag);
if (it == _map.end()) return ("");
else return (it->second);
}
};
inline bool operator< (const TagList &a, const TagList &b) {
std::map<std::string, std::string>::iterator it ;
for (it = a._map.begin(); it != a._map.end(); it++) {
std::string myVal1 = it->second;
std::string myVal2 = b._map.find(it->first);
if (myVal2 == "") return false;
if (strcmp(myVal1.c_str(),myVal2.c_str()) > 0) return true;
}
return false;
}
Hope someone can explain me the error message
Error 4 error C2679: binary '=' : no operator found which takes a right-hand operand of type 'std::_Tree_const_iterator<_Mytree>' (or there is no acceptable conversion) (...)
...and what is the reason for my confision....
Sorry, my fault...
found the answer by myself:
inline bool operator< (const TagList &a, const TagList &b) {
std::map<std::string, std::string>::const_iterator it ;
std::map<std::string, std::string>::const_iterator it2 ;
for (it = a._map.begin(); it != a._map.end(); it++) {
std::string myVal1 = it->second;
it2 = b._map.find(it->first);
std::string myVal2 = it2->second;
if (myVal2 == "") return false;
if (strcmp(myVal1.c_str(),myVal2.c_str()) > 0) return true;
}
return false;
}
it wasn't const
Thx
George

Pass a lamda expression in a thread pool

I try yo compile in C++11 the following piece of code without success. My goal is to use lambda expression instead of bind in order to fill a queue with tasks.
Could you please help me?
Is any case to create a dangling reference ?
#include <iostream>
#include <functional>
#include <queue>
using namespace std;
std::queue<std::function<void()>> funcs;
class A
{
public:
void foo(int a )
{
cout << "Hello word" << endl;
}
};
class ThePool
{
public:
template<typename _Callable, typename Object, typename... _Args>
void QueueFunction(_Callable __f, Object obj, _Args... __args)
{
funcs.push([=]()
{
(obj.*__f)((__args...));
});
}
void print(int i )
{
cout << "Hello Word"<< i <<endl;
}
};
int main(int argc, char** argv) {
ThePool t;
A a ;
t.QueueFunction(&A::foo,a,5);
std::function<void()> func = funcs.back();
func();
return 0;
}
The error that is generated is the following
main.cpp:24:38: error:
parameter packs not expanded with '...':
(obj.__f)((__args...));
^ main.cpp:24:38: note: '__args' main.cpp:24:44: error: expected ')' before '...' token
(obj.__f)((__args...));
^ main.cpp:24:49: error: expected ')' before ';' token
(obj.*__f)((__args...));
^ main.cpp: In function 'int main(int, char**)': main.cpp:39:45: error: conversion
from 'std::function' to non-scalar type
'std::function' requested
std::function func = funcs.back();
^ main.cpp: In instantiation of 'struct ThePool::QueueFunction(_Callable, Object,
_Args ...) [with _Callable = void (A::)(int); Object = A; _Args = {int}]::__lambda0': main.cpp:22:12: required from 'void
ThePool::QueueFunction(_Callable, Object, _Args ...) [with _Callable =
void (A::)(int); Object = A; _Args = {int}]' main.cpp:38:32:
required from here main.cpp:24:38: error: using invalid field
'ThePool::QueueFunction(_Callable, Object, _Args
...)::__lambda0::____args'
(obj.*__f)((__args...));

C++11 std::thread accepting function with rvalue parameter

I have some homework, and I have troubles understanding, (probably) how passing parameters to std::thread constructor works.
Assume following code (I deleted unneeded parts)
template<typename T, typename Task>
class Scheduler
{
private:
typedef std::unordered_map<std::size_t, T> Results;
class Solver
{
public:
Solver(Task&& task) : m_thread(&Solver::thread_function, std::move(task))
{
m_thread.detach();
}
Solver(Solver&& solver) = default; // required for vector::emplace_back
~Solver() = default;
private:
void thread_function(Task&& task)
{
task();
}
std::thread m_thread;
};
public:
Scheduler() = default;
~Scheduler() = default;
void add_task(Task&& task)
{
m_solvers.emplace_back(std::move(task));
}
private:
std::vector<Solver> m_solvers;
};
template<typename T>
struct Ftor
{
explicit Ftor(const T& t) : data(t) { }
T operator()() { std::cout << "Computed" << std::endl; return data; }
T data;
};
int main()
{
Scheduler<int, Ftor<int>> scheduler_ftor;
Scheduler<int, std::function<int(void)>> scheduler_lambda;
Ftor<int> s(5);
scheduler_ftor.add_task(std::move(s));
scheduler_lambda.add_task([](){ std::cout << "Computed" << std::endl; return 1; });
}
Why it doesn't compile?
MVS2015 is complaining about
functional(1195): error C2064: term does not evaluate to a function taking 1 arguments
functional(1195): note: class does not define an 'operator()' or a user defined conversion operator to a pointer-to-function or reference-to-function that takes appropriate number of arguments
note: while compiling class template member function 'Scheduler<int,Ftor<int> >::Solver::Solver(Task &&)'
While G++ 4.9.2
functional: In instantiation of ‘struct std::_Bind_simple<std::_Mem_fn<void (Scheduler<int, Ftor<int> >::Solver::*)(Ftor<int>&&)>(Ftor<int>)>’:
required from ‘void Scheduler<T, Task>::add_task(Task&&) [with T = int; Task = Ftor<int>]’
functional:1665:61: error: no type named ‘type’ in ‘class std::result_of<std::_Mem_fn<void (Scheduler<int, Ftor<int> >::Solver::*)(Ftor<int>&&)>(Ftor<int>)>’
typedef typename result_of<_Callable(_Args...)>::type result_type;
I suppose there are some problems with std::moving to std::thread.
If you use member function as first thread argument, second argument supposed to be this pointer, pointing to the object to which member function could be called to
UPDATE
Good discussion here
Start thread with member function
I don't follow your code, but addressing the question, a extrapolated answer will be( most of the code is psuedocode)
lets assume that there is a function int test(int name).
thread t0;
t0 = thread(test,32);
thread t1(test,43);
Passing a argument to function.
int temp = 0;
int testfunc(int& q)
{
cout<<q;
}
thread t1;
t1 = thread(testfunc,ref(temp));
In short, you just pass the name of the function that must be run in the thread as the first argument, and the functions parameters follow it in same order as they are in the function definition, for passing by reference you can use the ref() wrapper.See the below example.
#include <iostream>
#include <thread>
#include <string>
using namespace std;
void test(int a,int &a,string test)
{
\\do something
}
int main()
{
int test1 = 0;
string tt = "hello";
thread t1;
t1 = thread(23,&test1,tt);
t1.detach();
return 0;
}
if you are wondering about the use of join() and detach(), refer to this thread: When should I use std::thread::detach?, refer to my answer post in that thread.

Resources