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.
I am trying to make a linkedList but when I create a Head in a separate ADT with class Node Included in it it produces an error error C2143: syntax error : missing ';' before '*'
This is code for ADT of Node
#include <iostream>
#include "LinkedList.h"
using namespace std;
class Node
{
friend LinkedList;
protected:
int data;
Node *next;
public:
Node(int d =-999, Node *n = NULL);
//Mutators
void setData(int d);
void setNext(Node *n);
//Accessors
int getData ();
Node *getNext();
};
This is code for ADT LinkedList
class LinkedList
{
private:
Node *head; //This line is causing that particular error
public:
//some lines of code
};
I am completely lost tried every possible solution but can't figure out what's actually going wrong here.
I'm migrating the code of an dll, developed with C++, from Visual Studio version 2008 to 2010.
I'm facing this error below which is related to the 'C:\Program Files\Microsoft Visual Studio 10.0\VC\include\xstring'.
Error C2678: binary operator '!=': no operator found which takes a left-hand operand of type 'c_allocator<_Ty>' (or there is no acceptable conversion).
The error occurs with the line 'class c_allocator: public std::_Allocator_base<_Ty>{'.
#include <stdlib.h>
#include <vector>
#include "Synchro.h"
template<class _Ty>
class c_allocator: public std::_Allocator_base<_Ty>{
public:
typedef _Allocator_base<_Ty> _Mybase;
typedef typename _Mybase::value_type value_type;
typedef value_type _FARQ *pointer;
typedef value_type _FARQ& reference;
typedef const value_type _FARQ *const_pointer;
typedef const value_type _FARQ& const_reference;
typedef _SIZT size_type;
typedef _PDFT difference_type;
template<class _Other>struct rebind{
typedef c_allocator<_Other> other;
};
pointer address(reference _Val) const {
return (&_Val);
}
const_pointer address(const_reference _Val) const {
return (&_Val);
}
c_allocator() _THROW0() {
}
c_allocator(const c_allocator<_Ty>&) _THROW0() {
}
template<class _Other>c_allocator(const c_allocator<_Other>&) _THROW0() {
}
template<class _Other>c_allocator<_Ty>& operator=(const c_allocator<_Other>&) {
return (*this);
}
void deallocate(pointer _Ptr, size_type) {
CustomAlloc::LinearAllocHolder<1>::alloc.freemem(_Ptr);
}
pointer allocate(size_type _Count) {
return (pointer)CustomAlloc::LinearAllocHolder<1>::alloc.getmem(_Count*sizeof(value_type));
}
pointer allocate(size_type _Count, const void _FARQ *) {
return (allocate(_Count));
}
void construct(pointer _Ptr, const _Ty& _Val) {
std::_Construct(_Ptr, _Val);
}
void destroy(pointer _Ptr) {
std::_Destroy(_Ptr);
}
_SIZT max_size() const _THROW0() {
_SIZT _Count = (_SIZT)(-1) / sizeof (_Ty);
return (0 < _Count ? _Count : 1);
}
};
Any hint much appreciated -
thanks in advance -
surplus
I am attempting to create template classes where each can solve a specific facet of the problem so to be able to mishmash them without resorting to creating the traditional abstract virtual classes.
For that, I believe CRTP would be the best paradigm.
However, when using CRTP a bit more I found trapped on this weak resolution logic - compiler (g++ 4.8.2) cannot distinguish between two methods on different classes even though their signature is different - only the method name is the same.
The classes implementation:
template< class T >
class A {
public:
void foo( uint32_t val ) {
T* me = static_cast<T*>( this );
me->doit();
}
};
template< class T >
class B {
public:
void foo() {
uint32_t v32 = 10;
T* me = static_cast<T*>( this );
me->foo( v32 );
}
};
class Derived : public A<Derived>,
public B<Derived>
{
public:
void doit() {
std::cout << "here" << std::endl;
}
};
Then it is used as
Derived d;
d.foo();
When compiled, this error surfaces:
$ g++ -std=c++11 -c testLambda.cpp
testLambda.cpp: In function ‘int main(int, char**)’:
testLambda.cpp:102:7: error: request for member ‘foo’ is ambiguous
d.foo();
^
testLambda.cpp:25:10: note: candidates are: void B<T>::foo() [with T = Derived]
void foo() {
^
testLambda.cpp:16:10: note: void A<T>::foo(uint32_t) [with T = Derived; uint32_t = unsigned int]
void foo( uint32_t val ) {
Is this a compiler bug or the actual expected result?
User pubby8 at reddit.com/r/cpp responded (quote) a quick fix is to add this to Derived's class body:
using A<Derived>::foo;
using B<Derived>::foo;
I implemented a c++ function in a template class Valli<I>. I am using the Visual C++ IDE. There is always an error on while which is:
expected a declaration
I checked the code once and once again,and didn't find out anything wrong.
template<class I>
void Valli<I>::insert(I& new_item){
int front=0;
int rear=links.size()-1;
int mid=(front+rear)/2;
//this while loop binsearches the vector<iterator>
while(rear!=front){
if(new_item>links[mid]*){
front=mid;
mid=(front+rear)/2;
}else{
if(new_item<links[mid]*){
rear=mid;
mid=(front+rear)/2;
}else{
rear=mid;
front=mid;
}
}
}
...
...
}