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;
}
}
}
...
...
}
Related
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 have my project set to treat compiler warnings as errors and this seemingly trivial lambda capture is proving to be a head scratcher of an issue for me:
#pragma warning(default : 4626)
struct B{
B& operator=(const B&) = delete;
void f(){
auto l = [this](){ // <== compiler warning
/*body*/
};
}
};
int main(){
return 0;
}
The code above produces the following warning in MSVC 2019 (16.2.5):
warning C4626: 'B::f::<lambda_1>': assignment operator was implicitly defined as deleted
The warning is emitted for the lambda that captures this (and if I don't capture the this it compiles with no warnings).
Could someone explain to me the reason for the warning and if there's a way to write the code such that it compiles cleanly?
I understand that lambdas' assignment operators are implicitly deleted but not sure how (if) is that relevant to the warning I'm getting.
iam in a similar situation and reproduced the warning like this:
#pragma warning(default : 4626)
struct A
{
A& operator=(const A&) = delete;
};
struct B : public A
{
//B& operator=(const B&) = delete;
void f(){
auto l = [](){ // <== compiler warning
/*body*/
};
}
};
int main(){
return 0;
}
Compiled with /std:c++latest /W4
in my case it makes no difference if you capture this or not.
Is you class Inheriting from another class with a deleted operator= ?
I avoid that warning by explicitly deleting the operator= in my case.
This warning occured in MVS 19 16.3.0 compiling with /latest. with /std:c++17 there is no such warning.
EDIT
this warning also happens as soon something captured in the lamdba is used (captured by copy or ref doesnt matter):
#pragma warning(default : 4626)
int main()
{
int foo;
auto bar = [&]() {
foo;
};
return 0;
}
<source>(8): warning C4626: 'main::<lambda_1>': assignment operator was implicitly defined as deleted
(with /std:c++latest /W4)
I have some 15-year-old C++ code that I am trying to bring up to more modern times. At this stage, I'm trying to get code that compiled with Visual C++ 6.0 to now compile with VS 2003 (Microsoft Visual C++ .NET 69462-335-0000007-18915). If we can get this to compile cleanly & run properly, then we can take another step to get it into a more recent version of VS. But I'm having a number of problems...
Here is a snippet of the (simplified) code:
class toS
{
public:
toS() { buff[0] ='\0'; }
operator LPCTSTR() { return buff; }
protected:
void Append (TCHAR c)
{
LPTSTR p = buff + _tcslen(buff);
*p++ = c;
*p = '\0';
}
TCHAR buff[40];
};
class LtoS : public toS
{
public:
LtoS(LONG n, TCHAR c = '\0')
{
_ltot(n, buff, 10);
Append(c);
}
};
void WriteBool(const CString& Section, const CString& Key, bool Value);
CString Section;
int nLine = 0;
std::vector<bool> *BoolVect;
std::vector<bool>::iterator vi;
...
for (vi = BoolVect->begin(); vi != BoolVect->end(); vi++)
WriteBool(Section, "LineVis " + LtoS(nLine++), *vi);
...
From this I get the following error message:
error C2677: binary '+' : no global operator found which takes type 'LtoS' (or there is no acceptable conversion)
Any idea how this code ever worked? If I can find out what it did in the past, I can begin to define the overloaded operator+ to match the functionality.
Compiler error goes away when I make class tos inherit from CString with:
class tos : public CString { ... }
Hopefully this will not only compile, but will execute correctly...
Deriving from several of the comments, try adding a public conversion operator to class toS as follows:
operator LPCTSTR() const { return &buff[0]; }
You may need to explicitly construct the string in the for loop as well, e.g.:
WriteBool(Section, CString("LineVis ") + static_cast<LPCTSTR>(LtoS(nLine++)), *vi);
(Side note: As you probably know since you just extracted code for an example, there's a problem here:
std::vector<bool> BoolVect;
...
for (vi = BoolVect->begin(); vi != BoolVect->end(); vi++)
The notation you're using to access the BoolVect implies that it is a pointer, but it's not being declared as such in your example.)
I am upgrading a C++ project from MSVC 2008 to 2010, and because of the new CComBSTR move constructor [CComBSTR( CComBSTR&& )], I am getting a compiler error because of an ambiguous call.
Essentially, we have a String class, very similar to std::wstring that have a cast operator to CComBSTR. This is similator to the following code:
class CString {
public:
// ...
operator CComBSTR() {
CComBSTR temp;
/* Encoding conversion here */
return temp;
}
}
class CObjectConfig {
public:
CString GetName() const { return m_name; }
private:
CString m_name;
}
Now, at some places in the code, we do the following:
CObjectConfig config = GetObjectConfig();
CComBSTR objectName( config.GetName() );
In VS2008, this would work because the CString object would be implicitly converted to a CComBSTR rvalue and the copy constructor of CComBSTR (taking a const CComBSTR&) would be called to construct objectName.
In VS2010 with C++0x however, the compiler gives an ambiguous call error because CComBSTR rvalue seems to fit both the copy constructor and the move constructor.
While a bit clumsy, my solution to this problem is to static_cast the call to GetName:
CComBSTR objectName( static_cast<const CComBSTR&>( config.GetName() ) );
// or
CComBSTR objectName( static_cast<CComBSTR&&>( config.GetName() ) );
Both lines compile without error, but I need your advice on whether this is illegal, bad practice or undefined. Thank you.
This looks like a VC2010 bug to me. Either that, or I've incorrectly emulated your situation on my computer (I don't have VC2010). Here's what I'm doing:
#include <iostream>
class CComBSTR
{
public:
CComBSTR() {std::cout << "CComBSTR()\n";}
CComBSTR(const CComBSTR&) {std::cout << "CComBSTR(const CComBSTR&)\n";}
CComBSTR(CComBSTR&&) {std::cout << "CComBSTR(CComBSTR&&)\n";}
};
class CString {
public:
// ...
operator CComBSTR() {
CComBSTR temp;
/* Encoding conversion here */
return temp;
}
};
class CObjectConfig {
public:
CString GetName() const { return m_name; }
private:
CString m_name;
};
CObjectConfig GetObjectConfig()
{
return CObjectConfig();
}
int main()
{
CObjectConfig config = GetObjectConfig();
CComBSTR objectName( config.GetName() );
}
For me on g++-4.4 and clang (with -std=c++0x), this compiles fine. And it either calls or elides a call to CComBSTR(CComBSTR&&). My recommendation for working around this suspected bug is simply:
CComBSTR objectName( CComBSTR(config.GetName()) );
This is equivalent to your:
CComBSTR objectName( static_cast<CComBSTR&&>( config.GetName() ) );
but not as scary looking (and just as efficient). If you want to stay with the static_cast, then go with cast to CComBSTR&& as this will probably be more efficient than construction from a const lvalue.
I'm puzzled here, and kindly request your help.
VC2005SP1 swallows this (stripped out) code but gcc 4.0.1 bails out... Please point me the obvious mistake ?
TIA!
template<typename BCT, typename UIDT>
class Factory
{
public:
template<typename CT>
bool Register(UIDT UniqueID)
{
if (UniqueID > 10)
return(false);
CreateObject2<BCT, CT>;
return(true);
}
};
template <typename MC, typename MT>
class Manager : public Factory<MC, MT>
{
public:
bool RegisterType(const MT Type, const std::string TypeName)
{
return Factory<MC, MT>::Register<MC>(Type); // gcc claims "expected primary-expression before '>' at this point
}
};
VS is being kind.
return Factory<MC, MT>::template Register<MC>(Type); should work under both compilers.