I am really confused on why I am getting following compilation error.
Microsoft Visual Studio Compiler.
error C2678: binary '=' : no operator found which takes a left-hand operand of type 'const std::string' (or there is no acceptable conversion)
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <iterator>
class MyException {
public:
MyException( std::string message,
int line = 0) : m_message(message),
m_line(line) {}
const char* what() const throw(){
if ( m_line != 0 ) {
std::ostringstream custom_message;
custom_message << "Parsing Error occured at ";
custom_message << m_line << " Line : ";
custom_message << m_message;
m_message = custom_message.str();
}
return m_message.c_str();
}
private:
std::string m_message;
int m_line;
};
int main(int argc, char **argv) {
try {
// do something
}catch(MyException &e){
std::cout << e.what();
}
}
Error is coming at line
m_message = custom_message.str();
asked Aug 11, 2011 at 6:20
1
You declare the method as const
const char* what() const throw(){
but then you try to change the object
m_message = custom_message.str();
so you get an error.
What you should do instead is construct the custom message in the constructor.
class MyException {
public:
MyException(const std::string& message, int line = 0) :
m_message(message), m_line(line) {
if ( m_line != 0 ) {
std::ostringstream custom_message;
custom_message << "Parsing Error occured at ";
custom_message << m_line << " Line : ";
custom_message << m_message;
m_message = custom_message.str();
}
}
const char* what() const throw(){
return m_message.c_str();
}
private:
std::string m_message;
int m_line;
};
Also I changed your code to pass the std::string by reference, which is usual practice.
answered Aug 11, 2011 at 6:24
johnjohn
82k4 gold badges56 silver badges78 bronze badges
You are trying to assign to MyException::m_message
inside a const-qualified method MyException::what()
. Inside such what()
the entire *this
object is considered to be const
, which means that m_message
member is also const
. You can’t assign anything to a const-qualified std::string
object, since std::string
‘s assignment operator requires a modifiable (i.e. a non-const one) object on the left-hand side. You are supplying a const
one.
If you really want to be able to modify the m_message
inside what()
, you should declare it as mutable
member of the class (in this case it appears to be a good idea). Or use some other approach.
As @john noted, in your specific case it makes more sense to actually build m_message
in constructor instead of postponing it till what()
. I don’t really understand why you’d even want to rebuild your m_message
every time you call what()
. Unless your m_line
is expected to change somehow from one call to what()
to another, there’s really no need to do it every time.
answered Aug 11, 2011 at 6:24
In addition to the other answers;
You’re not including the <string>
header, which may be the cause of a problem later.
Something that used to get me a lot is that some std::
headers include others, which allows you to use a class, but maybe only with limited functionality because the std::
headers that they include are the bare minimum that is needed for that file to run. This is quite an annoyance because sometimes you declare a std::
class such as string
and you haven’t included the header, the definition will be fine but everything else may or may not work — leading you to a lot of debugging because the definition worked fine.
answered Aug 11, 2011 at 6:28
Seb HolzapfelSeb Holzapfel
3,7831 gold badge19 silver badges22 bronze badges
See the declaration of the what()
function, it is marked const
(the second const
on the line). That means that it cannot alter any member variables, in your case the m_message
string. That is why you get the error.
Now, how do you fix it?
Your code is wrong, your what()
function will prepend the "Parsing Error occured at "
etc. text each time you invoke the what()
function. So, instead of doing that having to modify the m_message
member, I suggest that you format the entire message in the ctor of the class:
MyException(std::string message, int line = 0)
{
if (line != 0)
{
std::ostringstream custom_message;
custom_message << "Parsing Error occured at ";
custom_message << line << " Line : ";
custom_message << message;
m_message = custom_message.str();
}
else
m_message = message;
}
answered Aug 11, 2011 at 6:36
wilxwilx
17.5k5 gold badges59 silver badges112 bronze badges
I get the following error:
error C2678: binary ‘=’: no operator found which takes a left-hand operand of type ‘const xe::kernel::shim::ParamBase<uint32_t>’
Now I am changing code from this:
SHIM_CALL XamUserAreUsersFriends_shim(PPCContext* ppc_context, KernelState* kernel_state) { uint32_t user_index = SHIM_GET_ARG_32(0); uint32_t unk1 = SHIM_GET_ARG_32(1); uint32_t unk2 = SHIM_GET_ARG_32(2); uint32_t out_value_ptr = SHIM_GET_ARG_32(3); uint32_t overlapped_ptr = SHIM_GET_ARG_32(4); XELOGD("XamUserAreUsersFriends(%d, %.8X, %.8X, %.8X, %.8X)", user_index, unk1, unk2, out_value_ptr, overlapped_ptr); if (user_index == 255) { user_index = 0; } SHIM_SET_MEM_32(out_value_ptr, 0); if (user_index) { // Only support user 0. SHIM_SET_RETURN_32(X_ERROR_NOT_LOGGED_ON); return; } X_RESULT result = X_ERROR_SUCCESS; const auto& user_profile = kernel_state->user_profile(); if (user_profile->signin_state() == 0) { result = X_ERROR_NOT_LOGGED_ON; } // No friends! SHIM_SET_MEM_32(out_value_ptr, 0); if (overlapped_ptr) { kernel_state->CompleteOverlappedImmediate(overlapped_ptr, result); SHIM_SET_RETURN_32(X_ERROR_IO_PENDING); } else { SHIM_SET_RETURN_32(result); } }
To this:
dword_result_t XamUserAreUsersFriends(dword_t user_index, unknown_t unk1, unknown_t unk2, lpvoid_t out_value_ptr, pointer_t<XAM_OVERLAPPED> overlapped_ptr) { if (user_index == 255) { user_index = 0; } *out_value_ptr = 0; if (user_index) { // Only support user 0. return X_ERROR_NOT_LOGGED_ON; } X_RESULT result = X_ERROR_SUCCESS; const auto& user_profile = kernel_state()->user_profile(); if (user_profile->signin_state() == 0) { result = X_ERROR_NOT_LOGGED_ON; } // No friends! *out_value_ptr = 0; if (overlapped_ptr) { kernel_state()->CompleteOverlappedImmediate(overlapped_ptr, result); return X_ERROR_IO_PENDING; } else { return result; } } DECLARE_XAM_EXPORT(XamUserAreUsersFriends, ExportTag::kImplemented);
According to this reference:
- using int_t =
const shim::ParamBase<int32_t>&; -
using word_t =
const shim::ParamBase<uint16_t>&; -
using dword_t =
const shim::ParamBase<uint32_t>&; -
using qword_t =
const shim::ParamBase<uint64_t>&; -
using float_t =
const shim::ParamBase<float>&; -
using double_t =
const shim::ParamBase<double>&; -
using lpvoid_t =
const shim::PointerParam&; -
using lpword_t =
const shim::PrimitivePointerParam<uint16_t>&; -
using lpdword_t =
const shim::PrimitivePointerParam<uint32_t>&; -
using lpqword_t =
const shim::PrimitivePointerParam<uint64_t>&; -
using lpfloat_t =
const shim::PrimitivePointerParam<float>&; -
using lpdouble_t =
const shim::PrimitivePointerParam<double>&; -
using lpstring_t =
const shim::StringPointerParam<char, std::string>&; -
using lpwstring_t
= const shim::StringPointerParam<wchar_t, std::wstring>&; -
using function_t =
const shim::ParamBase<uint32_t>&; -
using unknown_t =
const shim::ParamBase<uint32_t>&; -
using lpunknown_t
= const shim::PointerParam&; -
template <typename T>
-
using pointer_t =
const shim::TypedPointerParam<T>&;
The full error is: error C2678: binary ‘<‘ : no operator found which takes a left-hand operand of type ‘const sf::Vector2f’ (or there is no acceptable conversion)
What upsets me is that the error gives no location, so this could literally be anywhere in my program. Here is the function that I think does it, but I have plenty more to post if this isn’t it.
|
|
GetBoxes() and GetRect() return vectors of my Box class objects and sf::RectangleShape objects. What does this error even mean, and how do I get around it?
No way. Even the worst template errors give a line number. Post the contents of the output window.
The error is not in that code. The only < operator is in your for statement, and it is not using sf::Vector2f.
helios is right. The error message always has the line number in it (if it’s a compiler error). You just must not be seeing it.
Sorry, I meant no line number in my own code.
error C2678: binary ‘<‘ : no operator found which takes a left-hand operand of type ‘const sf::Vector2f’ (or there is no acceptable conversion) c:program files (x86)microsoft visual studio 11.0vcincludexstddef 180 1 TicTacToe
Looking in the xstddef file, I have no way of determining what actually went wrong
@Disch: ok, so how about this code? I am also working with a std map that holds an sf::Vector2f
|
|
That’s in Boad.cpp. Here’s board.h
|
|
Last edited on
Template errors output a sort of stack of errors and you have to figure out where your code is. That’s why I asked you to post the contents of the window. Post everything.
This:
std::map<sf::Vector2f, std::vector<Box>> boxMap;
std::map uses the < operator to order its keys. There is no < operator defined for sf::Vector2f.
You have a few options… the least drastic of which would be to provide your own compare functor for the map:
|
|
Last edited on
@helios: ok, here are all the warnings that come up with the one error:
Warning 1 warning C4018: ‘<‘ : signed/unsigned mismatch c:usersjordandocumentsvisual studio 2012 projectstictactoetictactoeboard.cpp 23 1 TicTacToe
Warning 2 warning C4244: ‘argument’ : conversion from ‘int’ to ‘float’, possible loss of data c:usersjordandocumentsvisual studio 2012projectstictactoetictactoeboard.cpp 25 1 TicTacToe
Warning 3 warning C4018: ‘<‘ : signed/unsigned mismatch c:usersjordandocumentsvisual studio 2012projectstictactoetictactoeboard.cpp 31 1 TicTacToe
Error 4 error C2678: binary ‘<‘ : no operator found which takes a left-hand operand of type ‘const sf::Vector2f’ (or there is no acceptable conversion) c:program files (x86)microsoft visual studio 11.0vcincludexstddef 180 1 TicTacToe
The locations the warnings refer to (Board.cpp) can be found in the code I posted earlier.
@Disch ok thanks, but what would a third element in my map do to how it functions?
Last edited on
wh1t3crayon: you still are not posting the full error message.
When I put similar code in VS (which it looks like you are using), I get the below error:
1> main.cpp 1>c:program files (x86)microsoft visual studio 11.0vcincludexstddef(180): error C2678: binary '<' : no operator found which takes a left-hand operand of type 'const sf::Vector2f' (or there is no acceptable conversion) 1> c:usersbenc++ libssfml-2.0includesfmlsystemtime.hpp(185): could be 'bool sf::operator <(sf::Time,sf::Time)' [found using argument-dependent lookup] 1> c:usersbenc++ libssfml-2.0includesfmlsystemstring.hpp(398): or 'bool sf::operator <(const sf::String &,const sf::String &)' [found using argument-dependent lookup] 1> c:usersbenc++ libssfml-2.0includesfmlwindowvideomode.hpp(141): or 'bool sf::operator <(const sf::VideoMode &,const sf::VideoMode &)' [found using argument-dependent lookup] 1> c:usersbenc++ libssfml-2.0includesfmlnetworkipaddress.hpp(227): or 'bool sf::operator <(const sf::IpAddress &,const sf::IpAddress &)' [found using argument-dependent lookup] 1> while trying to match the argument list '(const sf::Vector2f, const sf::Vector2f)' 1> c:program files (x86)microsoft visual studio 11.0vcincludexstddef(179) : while compiling class template member function 'bool std::less<_Ty>::operator ()(const _Ty &,const _Ty &) const' 1> with 1> [ 1> _Ty=sf::Vector2f 1> ] 1> c:program files (x86)microsoft visual studio 11.0vcincludemap(194) : see reference to function template instantiation 'bool std::less<_Ty>::operator ()(const _Ty &,const _Ty &) const' being compiled 1> with 1> [ 1> _Ty=sf::Vector2f 1> ] 1> c:program files (x86)microsoft visual studio 11.0vcincludetype_traits(743) : see reference to class template instantiation 'std::less<_Ty>' being compiled 1> with 1> [ 1> _Ty=sf::Vector2f 1> ] 1> c:program files (x86)microsoft visual studio 11.0vcincludextree(1028) : see reference to class template instantiation 'std::is_empty<_Ty>' being compiled 1> with 1> [ 1> _Ty=std::less<sf::Vector2f> 1> ] 1> c:program files (x86)microsoft visual studio 11.0vcincludemap(67) : see reference to class template instantiation 'std::_Tree<_Traits>' being compiled 1> with 1> [ 1> _Traits=std::_Tmap_traits<sf::Vector2f,std::vector<Box>,std::less<sf::Vector2f>,std::allocator<std::pair<const sf::Vector2f,std::vector<Box>>>,false> 1> ] 1> c:usersbendocumentsvisual studio 2012projectswxtimetestmain.cpp(28) : see reference to class template instantiation 'std::map<_Kty,_Ty>' being compiled 1> with 1> [ 1> _Kty=sf::Vector2f, 1> _Ty=std::vector<Box> 1> ]
The bolded/underlined section tells you where in my code the error was.
@Disch ok thanks, but what would a third element in my map do to how it functions?
There is not 3rd element. The map behaves exactly the same… it has one value per key. The only thing I changed is how it compares its keys.
std::map needs to be able to compare keys so that it can order them, and look up elements. By default, it uses the < operator to compare keys. However, as mentioned, sf::Vector2f has no operator, so we have to give it something else.
I gave it a VectorCompare struct so it will now use that struct to compare two sf::Vector2fs.
ah, you meant the build code. My apologies. So here is the full output:
|
|
1> Board.cpp 1>c:usersjordandocumentsvisual studio 2012projectstictactoetictactoeboard.cpp(23): warning C4018: '<' : signed/unsigned mismatch 1>c:usersjordandocumentsvisual studio 2012projectstictactoetictactoeboard.cpp(31): warning C4018: '<' : signed/unsigned mismatch 1>c:program files (x86)microsoft visual studio 11.0vcincludexstddef(180): error C2678: binary '<' : no operator found which takes a left-hand operand of type 'const sf::Vector2f' (or there is no acceptable conversion) 1> c:program files (x86)sfml-2.1includesfmlsystemtime.hpp(185): could be 'bool sf::operator <(sf::Time,sf::Time)' [found using argument-dependent lookup] 1> c:program files (x86)sfml-2.1includesfmlsystemstring.hpp(398): or 'bool sf::operator <(const sf::String &,const sf::String &)' [found using argument-dependent lookup] 1> c:program files (x86)sfml-2.1includesfmlwindowvideomode.hpp(141): or 'bool sf::operator <(const sf::VideoMode &,const sf::VideoMode &)' [found using argument-dependent lookup] 1> while trying to match the argument list '(const sf::Vector2f, const sf::Vector2f)' 1> c:program files (x86)microsoft visual studio 11.0vcincludexstddef(179) : while compiling class template member function 'bool std::less<_Ty>::operator ()(const _Ty &,const _Ty &) const' 1> with 1> [ 1> _Ty=sf::Vector2f 1> ] 1> c:program files (x86)microsoft visual studio 11.0vcincludemap(194) : see reference to function template instantiation 'bool std::less<_Ty>::operator ()(const _Ty &,const _Ty &) const' being compiled 1> with 1> [ 1> _Ty=sf::Vector2f 1> ] 1> c:program files (x86)microsoft visual studio 11.0vcincludetype_traits(743) : see reference to class template instantiation 'std::less<_Ty>' being compiled 1> with 1> [ 1> _Ty=sf::Vector2f 1> ] 1> c:program files (x86)microsoft visual studio 11.0vcincludextree(1028) : see reference to class template instantiation 'std::is_empty<_Ty>' being compiled 1> with 1> [ 1> _Ty=std::less<sf::Vector2f> 1> ] 1> c:program files (x86)microsoft visual studio 11.0vcincludemap(67) : see reference to class template instantiation 'std::_Tree<_Traits>' being compiled 1> with 1> [ 1> _Traits=std::_Tmap_traits<sf::Vector2f,std::vector<Box>,std::less<sf::Vector2f>,std::allocator<std::pair<const sf::Vector2f,std::vector<Box>>>,false> 1> ] 1> c:usersjordandocumentsvisual studio 2012projectstictactoetictactoeboard.h(29) : see reference to class template instantiation 'std::map<_Kty,_Ty>' being compiled 1> with 1> [ 1> _Kty=sf::Vector2f, 1> _Ty=std::vector<Box> 1> ] ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== |
Yeah, so…. you look at the bottom of that stack… and it tells you the line that the problem is on:
|
|
Line 29 of board.h.
Which is the line I pointed to before:
std::map<sf::Vector2f, std::vector<Box>> boxMap;
How do I use your version of the map? I have this so far, but I’m getting illegal indirection errors for it.
|
|
and then in my function
|
|
Error 4 error C2664: ‘std::_Tree_iterator<_Mytree> std::_Tree<_Traits>::insert(std::_Tree_const_iterator<_Mytree>,std::pair<_Ty1,_Ty2> &&)’ : cannot convert parameter 2 from ‘int’ to ‘std::pair<_Ty1,_Ty2> &&’ c:program files (x86)microsoft visual studio 11.0vcincludextree 1319 1 TicTacToe
Error 3 error C2100: illegal indirection c:program files (x86)microsoft visual studio 11.0vcincludextree 1319 1 TicTacToe
I’m pretty close to scrapping the map idea and finding some other way to link an area of coordinates to a class object. Are there easier ways to do this?
How do I use your version of the map?
Exactly the same as you would use your own version of the map. The only thing that really changes is the declaration line.
|
|
key.x=10 key.y=4 value=6 key.x=10 key.y=8 value=9 |
and then in my function [snip]
for(std::map<sf::Vector2f, std::vector<Box>, VectorCompare<float>>::const_iterator it = boxMap.begin(); it != boxMap.end(); ++it){
Good god, man. Use auto or at least typedef that madness:
|
|
I’m pretty close to scrapping the map idea and finding some other way to link an area of coordinates to a class object.
That might not be a bad idea. Using a Vector2f as a key seems extremely strange to me.
Can you elaborate on what you’re trying to do? Like at a high level, conceptual level?
Last edited on
Good god, man. Use auto or at least typedef that madness:
Thanks, you’re the first person to show me another way of even doing a for loop.
Can you elaborate on what you’re trying to do? Like at a high level, conceptual level?
Conceptually, I have a game board, class Board, that takes up the whole window. This board will be divided into 9 equal areas, defined by the class Box. E.g. a tic tac toe board. The Board holds a vector of 9 Box objects.
Conceptually, here is where I am stuck: I want to give each of these box objects an area of coordinates on the screen that defines them, and access them when clicked (i.e. if I click on the top left corner, then «box1» from the vector of Boxes is accessed, and I can do stuff such as draw its sprite.) I tried mapping some sfml rectangles to the box objects since sfml rectangles are graphical and can actually be placed invisibly on the screen. I just don’t know how to link the box objects to the sfml rectangle objects.
A simple grid can be accomplished with a 2D array. Although I hate using 2D arrays directly since their syntax is awkward… I usually abstract them behind another class.
Here’s something I whipped up recently that you can use:
|
|
Usage example:
|
|
I want to give each of these box objects an area of coordinates on the screen that defines them, and access them when clicked
Converting pixel coordinates to ‘grid’ coordinates is a simple division. Just divide by the number of pixels per grid entry.
Example:
|
|
Thank you for the replies. Your last post finally made me understand how templates work, but I too was hoping to avoid 2d arrays. I eventually got the code to work after thinking inside the Box (pun intended), and I just gave each box object their own sf::RectangleShape inside the box class. That way, the boxes are already linked to a set of coordinates upon creation. So for anybody else who is having a similar problem:
|
|
Then box’s constructor
|
|
Usage example:
|
|
Problem solved, thanks again.
Topic archived. No new replies allowed.
steptrainee 2 / 2 / 0 Регистрация: 03.05.2018 Сообщений: 101 |
||||
1 |
||||
12.11.2018, 20:26. Показов 8147. Ответов 11 Метки нет (Все метки)
Здравствуйте. Пытаюсь сравнить элемент массива с объектом,который я создаю в мейн и компилятор ругается «Severity Code Description Project File Line Suppression State
Заранее спасибо
__________________
0 |
New man 309 / 221 / 74 Регистрация: 23.05.2011 Сообщений: 981 |
||||||||
12.11.2018, 20:40 |
2 |
|||||||
Смотри, в массиве ты хранишь собак, а в функцию ты передаёшь указатель на собаку.
Добавлено через 1 минуту
Надо И да, удаляй за собой память.
1 |
2 / 2 / 0 Регистрация: 03.05.2018 Сообщений: 101 |
|
12.11.2018, 22:10 [ТС] |
3 |
К сожаление, это не помогло, все та же ошибка(((. Может, нужно перегрузить оператор ==?
0 |
309 / 221 / 74 Регистрация: 23.05.2011 Сообщений: 981 |
|
13.11.2018, 01:08 |
4 |
steptrainee, естественно.
0 |
2 / 2 / 0 Регистрация: 03.05.2018 Сообщений: 101 |
|
13.11.2018, 21:28 [ТС] |
5 |
Вы знаете как исправить данную проблему ?
0 |
Kuzia domovenok 3985 / 3255 / 909 Регистрация: 25.03.2012 Сообщений: 12,102 Записей в блоге: 1 |
||||
13.11.2018, 21:45 |
6 |
|||
0 |
2 / 2 / 0 Регистрация: 03.05.2018 Сообщений: 101 |
|
14.11.2018, 18:22 [ТС] |
7 |
Такая перегрузка не работает. Сравнивается тип List<T> с объектом, который приходит с мейна
0 |
anapshy 282 / 253 / 211 Регистрация: 14.11.2016 Сообщений: 963 |
||||
14.11.2018, 18:33 |
8 |
|||
steptrainee, а вы думаете std::equal без Добавлено через 1 минуту
откуда вы знаете что передаст пользователь? Программе уже известно, что объект класса List принимает только собак Добавлено через 1 минуту
1 |
3985 / 3255 / 909 Регистрация: 25.03.2012 Сообщений: 12,102 Записей в блоге: 1 |
|
14.11.2018, 18:35 |
9 |
steptrainee, и что с того? Ты хочешь в один лист намешать и собак и ещё кого-то? Так не бывает, какой же это тогда лист?
0 |
anapshy 282 / 253 / 211 Регистрация: 14.11.2016 Сообщений: 963 |
||||
14.11.2018, 18:42 |
10 |
|||
Сообщение было отмечено steptrainee как решение РешениеИсправил
1 |
2 / 2 / 0 Регистрация: 03.05.2018 Сообщений: 101 |
|
14.11.2018, 19:38 [ТС] |
11 |
Спасибо, у вас лучший ответ, все грамотно и конкретно, что я и искал, действительно работает. Я однажды пробовал дружественно перегрузить, но ничего не заработало и я сдался.
0 |
anapshy 282 / 253 / 211 Регистрация: 14.11.2016 Сообщений: 963 |
||||
14.11.2018, 19:58 |
12 |
|||
steptrainee, не только в этом ошибка.
0 |
I’m trying trying to to use std::swap and std::reverse with my class:
struct Vector2i
{
int col;
int row;
const Vector2i& operator=( const Vector2i& rhs );
};
where the assignment operator is defined as:
const Vector2i& Vector2i::operator=( const Vector2i& rhs )
{
if( this == &rhs )
{
return *this;
}
col = rhs.col;
row = rhs.row;
return *this;
}
However I’m unable to get the assignment operator right.
I’ve tried mixing the return and argument types around
(const Vector2i&
, Vector2i&
, const Vector2i
, Vector2i
)
but it won’t work.
Any ideas why that is?
This is the what the error points to in the STL swap implementation:
template<class _Ty> inline
void swap(_Ty& _Left, _Ty& _Right)
_NOEXCEPT_OP(is_nothrow_move_constructible<_Ty>::value
&& is_nothrow_move_assignable<_Ty>::value)
{ // exchange values stored at _Left and _Right
_Ty _Tmp = _Move(_Left);
_Left = _Move(_Right); /* <<<< here and */
_Right = _Move(_Tmp); /* <<<< here */
}
This why I get in Output in Visual Studio when I try to build it:
1>c:program files (x86)microsoft visual studio 12.0vcincludeutility(53): error C2678: binary '=' : no operator found which takes a left-hand operand of type 'const Vector2i' (or there is no acceptable conversion)
1> c:userserikdocumentsvisual studio 2013projects2d-cmd-dungeoncrawler2d-cmd-dungeoncrawlervector2i.h(13): could be 'const Vector2i &Vector2i::operator =(const Vector2i &)'
1> while trying to match the argument list '(const Vector2i, const Vector2i)'
1> c:program files (x86)microsoft visual studio 12.0vcincludeutility(28) : see reference to function template instantiation 'void std::swap<const Vector2i>(_Ty &,_Ty &)' being compiled
1> with
1> [
1> _Ty=const Vector2i
1> ]
1> c:program files (x86)microsoft visual studio 12.0vcincludexutility(3161) : see reference to function template instantiation 'void std::iter_swap<_BidIt,_BidIt>(_FwdIt1,_FwdIt2)' being compiled
1> with
1> [
1> _BidIt=std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<Vector2i>>,std::_Iterator_base0>
1> , _FwdIt1=std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<Vector2i>>,std::_Iterator_base0>
1> , _FwdIt2=std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<Vector2i>>,std::_Iterator_base0>
1> ]
1> c:program files (x86)microsoft visual studio 12.0vcincludexutility(3168) : see reference to function template instantiation 'void std::_Reverse<std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<Vector2i>>,std::_Iterator_base0>>(_BidIt,_BidIt,std::bidirectional_iterator_tag)' being compiled
1> with
1> [
1> _BidIt=std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<Vector2i>>,std::_Iterator_base0>
1> ]
1> c:userserikdocumentsvisual studio 2013projects2d-cmd-dungeoncrawler2d-cmd-dungeoncrawlerastaralgorithm.cpp(135) : see reference to function template instantiation 'void std::reverse<std::_List_const_iterator<std::_List_val<std::_List_simple_types<Vector2i>>>>(_BidIt,_BidIt)' being compiled
1> with
1> [
1> _BidIt=std::_List_const_iterator<std::_List_val<std::_List_simple_types<Vector2i>>>
1> ]
1>c:program files (x86)microsoft visual studio 12.0vcincludeutility(54): error C2678: binary '=' : no operator found which takes a left-hand operand of type 'const Vector2i' (or there is no acceptable conversion)
1> c:userserikdocumentsvisual studio 2013projects2d-cmd-dungeoncrawler2d-cmd-dungeoncrawlervector2i.h(13): could be 'const Vector2i &Vector2i::operator =(const Vector2i &)'
1> while trying to match the argument list '(const Vector2i, const Vector2i)'
Hi @vldbnc. I see the same problem and is quite different from this issue: binary ‘<‘: no operator found.
It got following:
1>sparse_column_iterable.cc
1>C:Program Files (x86)Microsoft Visual Studio2017EnterpriseVCToolsMSVC14.12.25827includealgorithm(2417): error C2678: binary ‘*’: no operator found which takes a left-hand operand of type ‘const tensorflow::boosted_trees::utils::anonymous-namespace'::IndicesRowIterator' (or there is no acceptable conversion) 1>D:...tensorflowtensorflowcontribboosted_treeslibutilssparse_column_iterable.cc(54): note: could be 'const __int64 &tensorflow::boosted_trees::utils::
anonymous-namespace’::IndicesRowIterator::operator *(void)’
1>C:Program Files (x86)Microsoft Visual Studio2017EnterpriseVCToolsMSVC14.12.25827includealgorithm(2417): note: while trying to match the argument list ‘(const tensorflow::boosted_trees::utils::anonymous-namespace'::IndicesRowIterator)' 1>C:Program Files (x86)Microsoft Visual Studio2017EnterpriseVCToolsMSVC14.12.25827includealgorithm(2439): note: see reference to function template instantiation '_FwdIt std::_Lower_bound_unchecked<_Iter,_Ty,_Fn>(_FwdIt,_FwdIt,const _Ty &,_Pr)' being compiled 1> with 1> [ 1> _FwdIt=tensorflow::boosted_trees::utils::
anonymous-namespace’::IndicesRowIterator,
1> _Iter=tensorflow::boosted_trees::utils::anonymous-namespace'::IndicesRowIterator, 1> _Ty=tensorflow::int64, 1> _Fn=std::less<void>, 1> _Pr=std::less<void> 1> ] 1>C:Program Files (x86)Microsoft Visual Studio2017EnterpriseVCToolsMSVC14.12.25827includealgorithm(2447): note: see reference to function template instantiation '_FwdIt std::lower_bound<_FwdIt,_Ty,std::less<void>>(_FwdIt,_FwdIt,const _Ty &,_Pr)' being compiled 1> with 1> [ 1> _FwdIt=tensorflow::boosted_trees::utils::
anonymous-namespace’::IndicesRowIterator,
1> _Ty=tensorflow::int64,
1> _Pr=std::less
1> ]
1>D:….tensorflowtensorflowcontribboosted_treeslibutilssparse_column_iterable.cc(119): note: see reference to function template instantiation ‘_FwdIt std::lower_boundtensorflow::boosted_trees::utils::`anonymous-namespace’::IndicesRowIterator,tensorflow::int64(_FwdIt,_FwdIt,const _Ty &)’ being compiled
1> with
1> [
1> _FwdIt=tensorflow::boosted_trees::utils::`anonymous-namespace’::IndicesRowIterator,
1> _Ty=tensorflow::int64
1> ]
1>C:Program Files (x86)Microsoft Visual Studio2017EnterpriseVCToolsMSVC14.12.25827includealgorithm(2417): error C2100: illegal indirection
1>Done building project «tf_core_kernels.vcxproj» — FAILED.
###System information
tensorflow 1.5.0RC
Windows 10
VisualStudio Prof. 2017
CMake 3.10.1
Добавлено 9 апреля 2021 в 17:26
Предыдущие уроки познакомили нас с множеством терминов и концепций, которые мы будем использовать практически в каждой создаваемой нами программе. В этом уроке мы рассмотрим процесс интеграции этих знаний в нашу первую простую программу.
Умножение на 2
Во-первых, давайте создадим программу, которая просит пользователя ввести целое число, ждет, когда он введет целое число, а затем сообщает ему, чему будет равно это число, умноженное два. Программа должна выдать следующий результат (предположим, я ввел 4 в качестве входных данных):
Enter an integer: 4
Double that number is: 8
Как справиться с этой задачей? Пошагово.
Лучшая практика
Программисты-новички часто пытаются написать всю программу сразу, а затем теряются, когда она выдает много ошибок. Лучшая стратегия – добавлять по одному элементу за раз, проверять его компиляцию и тестировать. Затем, когда вы убедитесь, что один элемент работает, переходите к следующему фрагменту.
Мы используем эту стратегию и здесь. По мере прохождения каждого шага набирайте (не копируйте/вставляйте) каждую программу в своей IDE, компилируйте и запускайте ее.
Сначала создайте новый консольный проект.
Теперь давайте начнем с основного каркаса. Мы знаем, что нам понадобится функция main()
(поскольку она должна быть во всех программах на C++), поэтому, если ваша среда IDE не создала эту функцию пустой при создании нового проекта, давайте создадим ее сами:
int main()
{
return 0;
}
Мы знаем, что нам нужно будет выводить текст в консоль и получать текст с клавиатуры пользователя, поэтому нам нужно включить iostream
для доступа к std::cout
и std::cin
.
#include <iostream>
int main()
{
return 0;
}
Теперь давайте сообщим пользователю, что нам нужно ввести целое число:
#include <iostream>
int main()
{
std::cout << "Enter an integer: ";
return 0;
}
На этом этапе ваша программа должна выдать такой результат:
Enter an integer:
а затем завершиться.
Далее мы собираемся получить от пользователя входные данные. Для этого мы будем использовать std::cin
и operator>>
. Но нам также необходимо определить переменную для хранения этого входного значения, чтобы использовать его в дальнейшем.
#include <iostream>
int main()
{
std::cout << "Enter an integer: ";
int num{ 0 }; // определяем переменную num как целочисленную переменную
std::cin << num; // получаем целочисленное значение с клавиатуры пользователя
return 0;
}
Пора скомпилировать наши изменения… и…
Ой! Вот что автор получил в Visual Studio 2017:
1>------ Build started: Project: Double, Configuration: Release Win32 ------
1>Double.cpp
1>c:vcprojectsdoubledouble.cpp(8): error C2678: binary '<<': no operator found which takes a left-hand operand of type 'std::istream' (or there is no acceptable conversion)
1>c:vcprojectsdoubledouble.cpp: note: could be 'built-in C++ operator<<(bool, int)'
1>c:vcprojectsdoubledouble.cpp: note: while trying to match the argument list '(std::istream, int)'
1>Done building project "Double.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Мы столкнулись с ошибкой компиляции!
Во-первых, поскольку программа компилировалась до того, как мы сделали это последнее обновление, и не компилируется сейчас, ошибка должна быть в только что добавленном коде (строки 7 и 8). Это значительно сокращает объем кода, который мы должны проверить, чтобы найти ошибку. Строка 7 довольно проста (просто определение переменной), поэтому здесь ошибки, вероятно, нет. Под подозрением остается строка 8.
Во-вторых, это сообщение об ошибке нелегко прочитать. Но давайте выделим некоторые ключевые элементы: компилятор сообщает нам, что он обнаружил ошибку в строке 8. Это означает, что фактическая ошибка, вероятно, находится в строке 8 или, возможно, в предыдущей строке, что подтверждает нашу предыдущую оценку. Затем компилятор сообщает вам, что не смог найти оператор ‘<<
‘ с левым операндом типа std::istream
(который является типом std::cin
). Другими словами, operator<<
не знает, что делать с std::cin
, поэтому ошибка должна быть либо в использовании std::cin
, либо в использовании operator<<
.
Теперь видите ошибку? Если нет, посмотрите еще.
Вот программа, содержащая исправленный код:
#include <iostream>
int main()
{
std::cout << "Enter an integer: ";
int num{ 0 };
std::cin >> num; // std::cin использует оператор >>, а не оператор <<!
return 0;
}
Теперь программа компилируется, и мы можем ее протестировать. Программа будет ждать, пока вы введете число, поэтому давайте введем 4. Результат должен выглядеть следующим образом:
Enter an integer: 4
Почти готово! Последний шаг – удвоить число.
Как только мы закончим этот последний шаг, наша программа скомпилируется и успешно запустится, выдав желаемый результат.
Есть (по крайней мере) 3 способа сделать это. Пойдем от худшего к лучшему.
Плохое решение
#include <iostream>
// худшая версия
int main()
{
std::cout << "Enter an integer: ";
int num{ 0 };
std::cin >> num;
num = num * 2; // удваиваем значение num, а затем присваиваем это значение обратно num
std::cout << "Double that number is: " << num << 'n';
return 0;
}
В этом решении мы используем выражение для умножения num
на 2, а затем присваиваем это значение обратно num
. С этого момента num
будет содержать наше удвоенное число.
Почему это плохое решение:
- Перед оператором присваивания
num
содержит введенные пользователем данные. После присваивания оно содержит другое значение. Это сбивает с толку. - Мы перезаписали входные данные пользователя, присвоив новое значение входной переменной, поэтому, если мы захотим расширить нашу программу, чтобы сделать что-то еще с этим входным значением позже (например, утроить входное значение пользователя), но оно уже будет потеряно.
Почти хорошее решение
#include <iostream>
// менее плохая версия
int main()
{
std::cout << "Enter an integer: ";
int num{ 0 };
std::cin >> num;
// определяем новую переменную и инициализируем ее с num * 2
int doublenum{ num * 2 };
// затем печатаем значение этой переменной
std::cout << "Double that number is: " << doublenum << 'n';
return 0;
}
Это решение довольно просто читать и понимать, и оно решает обе проблемы, возникающие при наихудшем решении.
Основным недостатком здесь является то, что мы определяем новую переменную (что добавляет сложности) для хранения значения, которое мы используем только один раз. Мы можем добиться большего.
Предпочтительное решение
#include <iostream>
// предпочтительная версия
int main()
{
std::cout << "Enter an integer: ";
int num{ 0 };
std::cin >> num;
// используем выражение для умножения num * 2 в точке, где мы собираемся его напечатать
std::cout << "Double that number is: " << num * 2 << 'n';
return 0;
}
Это предпочтительное решение из всех. Когда выполняется std::cout
, вычисляется выражение num * 2
, и результатом будет удвоенное значение num
. Это значение будет напечатано. Само значение в num
не будет изменено, поэтому мы можем использовать его позже, если захотим.
Эта версия является нашим эталонным решением.
Примечание автора
Первая и основная цель программирования – заставить вашу программу работать. Программа, которая не работает, бесполезна, независимо от того, насколько хорошо она написана.
Но лучшее решение часто неочевидно, и наши первые решения задач обычно не так хороши, как могли бы быть.
Когда мы сосредоточены на выяснении того, как заставить наши программы работать, нет особого смысла тратить много времени на код, который мы даже не знаем, сохраним ли. Так мы идем по сокращенному пути. Мы пропускаем такие вещи, как обработка ошибок и комментарии. Мы добавляем отладочный код в наше решение, чтобы помочь нам диагностировать проблемы и находить ошибки. Мы учимся по ходу дела – вещи, которые, как мы думали, могут сработать, в конце концов не работают, и мы должны отступить и попробовать другой подход.
Конечным результатом является то, что наши первоначальные решения часто недостаточно хорошо структурированы, надежны (устойчивы к ошибкам), читабельны или кратки. Итак, как только ваша программа заработает, ваша работа на самом деле не закончена (если только программа не является одноразовой). Следующим шагом будет очистка вашего кода. Это включает в себя такие вещи, как удаление (или закомментирование) временного/отладочного кода, добавление комментариев, обработка случаев ошибок, форматирование кода и обеспечение соблюдения передовых практик. И даже тогда ваша программа может быть не такой простой, как могла бы быть – возможно, есть избыточная логика, которую можно объединить, или несколько операторов, которые тоже можно объединить, или переменные, которые не нужны, или тысяча других мелочей, которые можно было бы упростить. Слишком часто начинающие программисты сосредотачиваются на оптимизации для повышения производительности, тогда как им следует оптимизировать для удобства обслуживания.
Очень немногие из решений, представленных в этих руководствах, оказались отличными с первого раза. Скорее, они являются результатом постоянного совершенствования до тех пор, пока не будет найдено ничего, что можно было бы улучшить. И во многих случаях читатели по-прежнему находят множество вещей, которые можно предложить для улучшения!
Всё это на самом деле для того, чтобы сказать: не расстраивайтесь, если/когда ваши решения не выходят чудесно оптимизированными прямо из вашего мозга. Это нормально. Совершенство в программировании – это итеративный процесс (требующий многократных проходов).
Примечание автора
Еще одна вещь: вы можете подумать: «В C++ так много правил и концепций. Как мне всё это запомнить? ».
Короткий ответ: Никак. Использование того, что вы знаете в C++, – одна треть, оставшиеся две трети – это поиск, как сделать всё остальное.
Когда вы впервые читаете этот сайт, меньше сосредотачивайтесь на запоминании деталей и больше на понимании того, что возможно. Затем, когда вам нужно будет что-то реализовать в программе, которую вы будете писать, вы можете вернуться сюда (или на справочный сайт) и освежить в памяти, как это сделать.
Небольшой тест
Вопрос 1
Измените решение, показанное выше, на «лучшее решение» так, чтобы его вывод был следующим (при условии, что пользователь ввел 4):
Enter an integer: 4
Double 4 is: 8
Triple 4 is: 12
Ответ
#include <iostream>
int main()
{
std::cout << "Enter an integer: ";
int num{ 0 };
std::cin >> num;
std::cout << "Double " << num << " is: " << num * 2 << 'n';
std::cout << "Triple " << num << " is: " << num * 3 << 'n';
return 0;
}
Теги
C++ / CppLearnCppДля начинающихОбучениеПрограммирование