Error a template declaration cannot appear at block scope

I'm learning Lipmann and I'm only studying. I'm trying here to write a code that will return a minimal element in a vector. When I compile my code in Codeblocks, it says: "A template declaration ca...

You cannot define template inside a function, and main is a function. You need to define your min function template outside of main, before it.

You have several other problems in your code. The

template <class elemType>

must appear immediately before the function definition. Putting

elemType save;

between them is not correct syntax.

Another problem is your algorithm for selecting the min value in a vector. Why do you have this

if (*save < *(it + 1) ) { save = *it; }

and this

if (*save < *it ) { save = *it; }

at the same time?

Here’s what you probably want:

#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

template <class elemType>
const elemType& min(const std::vector<elemType>& vec) {
  typename std::vector<elemType>::const_iterator
    select = vec.begin(),
    it = std::next(select),
    end = vec.end();
  for ( ; it != end; ++it ) {
    if ( *it < *select ) select = it;
  }
  return *select;
};

int main() {
  int massiv[10] = {35, 66, 98, 15, 32, 41, 24, 90, 55, 100};
  std::vector<int> vec_train(massiv,massiv+10);

  std::cout << min(vec_train) << std::endl;
  return 0;
}

If you need to handle empty vectors, you could add

if (!vec.size()) throw std::length_error("empty vector passed to min");

at the beginning of the function, or return an iterator instead of element reference, as end() is well defined even for empty vectors.

here is my code:

#include <iostream>
using namespace std;
template<typename T>
class List
{
    public:
        List(T);
};
template<typename T>
class A: public List<T>
{
    public:
};
int main()
{   //my problem is here...!
    A a(10);
}

I don’t know how to declare this class in main and use it.
In this case, I have this error:

missing template arguments before ‘a’

and when I write:

template(typename T)
   A a(10);

I give this error:

g++ -std=c++11 -c main.cpp
error: a template declaration cannot appear at block scope
template
^~~~~~~~

asmmo's user avatar

asmmo

6,8421 gold badge10 silver badges24 bronze badges

asked May 21, 2020 at 1:32

twinkle little star's user avatar

Since u didn’t write a constructor for A, I supposed u want to use the inherited one, hence u have to provide the following line in A

using List<T>::List;

And since u used c++11, u have to provide the template arg, as follows

A<int> a(10);

If u want to make the compiler figure it out, use c++17 or c++20 and provide the following guide

template<class T> A(T)-> A<T>;

Now the full code with c++17 will be

template<typename T>
class List
{
public:
    List(T) {}
};
template<typename T>
class A: public List<T>
{
public:
    using List<T>::List;
};
template<class T> A(T)-> A<T>;
int main()
{   //No problem here...!
    A a(10);
}

And with c++11 will be

template<typename T>
class List
{
public:
    List(T) {}
};
template<typename T>
class A: public List<T>
{
public:
    using List<T>::List;
};


int main()
{   //No problem here...!
    A<int> a(10);
}

answered May 21, 2020 at 2:02

asmmo's user avatar

asmmoasmmo

6,8421 gold badge10 silver badges24 bronze badges

0

std::vector 

is templated, so you call it as std::vector<int> for example. As such, your declaration should be A<int> a(10);

answered May 21, 2020 at 1:36

Jordan's user avatar

JordanJordan

401 silver badge9 bronze badges

я пытаюсь небольшой пример, чтобы начать с Spirit X3.

template <typename Iterator>
bool parser(Iterator& first, Iterator const& last)
{
using namespace x3;

x3::rule<class quote,std::string> const quote = "quote";
auto quote_def = '"' >> *(char_-'"') >> '"';

//   x3::rule<class header,std::vector<std::string>> const header = "header";
//  auto header_def = quote % ',';

BOOST_SPIRIT_DEFINE(quote);

return true;
}

int main(int argc, char** argv)
{
std::string test = ""abc","def"";

auto it=std::begin(test);
parser( it, std::end(test));

return 0;
}

И я получаю следующую ошибку компилятора:

In file included from /home/robstr/Downloads/boost_1_60_0/boost/spirit/home/x3/nonterminal.hpp:10:0,
from /home/robstr/Downloads/boost_1_60_0/boost/spirit/home/x3.hpp:17,
from tmp.cc:5:
tmp.cc: In function ‘bool parser(Iterator&, const Iterator&)’:
/home/robstr/Downloads/boost_1_60_0/boost/spirit/home/x3/nonterminal/rule.hpp:157:5: error: a template declaration cannot appear at block scope
template <typename Iterator, typename Context, typename Attribute>          
^
/home/robstr/Downloads/boost_1_60_0/boost/preprocessor/seq/for_each.hpp:83:61: note: in expansion of macro ‘BOOST_SPIRIT_DEFINE_’
# define BOOST_PP_SEQ_FOR_EACH_M_I(r, macro, data, seq, sz) macro(r, data, BOOST_PP_SEQ_HEAD(seq))
^
/home/robstr/Downloads/boost_1_60_0/boost/preprocessor/seq/for_each.hpp:78:47: note: in expansion of macro ‘BOOST_PP_SEQ_FOR_EACH_M_I’
#    define BOOST_PP_SEQ_FOR_EACH_M_IM(r, im) BOOST_PP_SEQ_FOR_EACH_M_I(r, im)
^
/home/robstr/Downloads/boost_1_60_0/boost/preprocessor/seq/for_each.hpp:77:43: note: in expansion of macro ‘BOOST_PP_SEQ_FOR_EACH_M_IM’
#    define BOOST_PP_SEQ_FOR_EACH_M(r, x) BOOST_PP_SEQ_FOR_EACH_M_IM(r, BOOST_PP_TUPLE_REM_4 x)
^
/home/robstr/Downloads/boost_1_60_0/boost/preprocessor/seq/for_each.hpp:77:73: note: in expansion of macro ‘BOOST_PP_TUPLE_REM_4’
#    define BOOST_PP_SEQ_FOR_EACH_M(r, x) BOOST_PP_SEQ_FOR_EACH_M_IM(r, BOOST_PP_TUPLE_REM_4 x)
^
/home/robstr/Downloads/boost_1_60_0/boost/preprocessor/control/iif.hpp:32:31: note: in expansion of macro ‘BOOST_PP_SEQ_FOR_EACH_M’
# define BOOST_PP_IIF_1(t, f) t
^
/home/robstr/Downloads/boost_1_60_0/boost/preprocessor/repetition/detail/for.hpp:22:37: note: in expansion of macro ‘BOOST_PP_FOR_1_C’
# define BOOST_PP_FOR_1(s, p, o, m) BOOST_PP_FOR_1_C(BOOST_PP_BOOL(p(2, s)), s, p, o, m)
^
/home/robstr/Downloads/boost_1_60_0/boost/preprocessor/cat.hpp:29:34: note: in expansion of macro ‘BOOST_PP_FOR_1’
#    define BOOST_PP_CAT_I(a, b) a ## b
^
/home/robstr/Downloads/boost_1_60_0/boost/preprocessor/control/iif.hpp:32:31: note: in expansion of macro ‘BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK_EXEC’
# define BOOST_PP_IIF_1(t, f) t
^
/home/robstr/Downloads/boost_1_60_0/boost/preprocessor/seq/for_each.hpp:29:53: note: in expansion of macro ‘BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK’
#    define BOOST_PP_SEQ_FOR_EACH(macro, data, seq) BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK(macro, data, seq)
^
/home/robstr/Downloads/boost_1_60_0/boost/spirit/home/x3/nonterminal/rule.hpp:169:34: note: in expansion of macro ‘BOOST_PP_SEQ_FOR_EACH’
#define BOOST_SPIRIT_DEFINE(...) BOOST_PP_SEQ_FOR_EACH(                         
^
src/dico.cc:21:1: note: in expansion of macro ‘BOOST_SPIRIT_DEFINE’
BOOST_SPIRIT_DEFINE(quote);
^

Проблема в том, я думаю BOOST_SPIRIT_DEFINE но я понятия не имею, как это исправить.

1

Решение

После игры arround я нашел решение:

Вам нужно заключить правило в собственное пространство имен:

namespace grammer
{
using namespace x3;

x3::rule<class quote,std::string> const quote = "quote";
auto quote_def = '"' >> *(char_-'"') >> '"';

x3::rule<class header,std::vector<std::string>> const header = "header";
auto header_def = quote % ',';BOOST_SPIRIT_DEFINE(quote, header);
}template <typename Iterator>
bool parser(Iterator& first, Iterator const& last)
{
using namespace x3;
std::vector<std::string> headerVec;

auto ret = x3::parse( first, last, grammer::header , headerVec);
if(ret)
std::cout << "all done " << headerVec.size() <<"n";
else
{
std::cout << "not : " << headerVec.size() <<"n";
}
return true;
}

Но я не могу объяснить, почему это решает ошибку компилятора.

0

Другие решения

Других решений пока нет …

Hello, I’m working on a program which implements a Hash Table. I want to call a member function which is intended to hash a string to an integer value. However, I keep getting compiler errors with regards to how I am calling my hashcode function for hashing the strings being generated in main to integers. Specifically, with the given edition of the code below I am getting the errors:

template_code.cpp: In function ‘int main()’:
template_code.cpp:208: error: expected primary-expression before ‘template’
template_code.cpp:208: error: expected ‘;’ before ‘template’

Thanks for any help.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

#include <iostream>
#include <cstddef>
#include <string>
#include <cmath>
#include <ctime>
#include <cstdlib>

using namespace std;

void print_menu();
template <typename KEY, typename VALUE> //Defining template values
class Entry //Defining Entry Class
{
	template<typename K, typename V> friend class HashTable; //Including HashTable function as friend

	private:
		KEY key;
		VALUE value;
		Entry * next_entry;

	public:
		/*** Constructors ***/
		Entry(void) : key(KEY()), value(VALUE()), next_entry(NULL) {} 
		//If you would like you can convert constructors to have this look
		Entry(KEY key, VALUE value)
		{
			this->template key = key;
			this->template value = value;
			this->template next_entry = NULL;
		}
		Entry(KEY key, VALUE value, Entry * next) : key(key), value(value), next_entry(next) {}

		//accessors
		KEY get_key() { return key; }
		VALUE get_value() { return value; }
		Entry * get_next_entry() { return next_entry; }

		//mutators
		void set_key(KEY key) { this.key = key; }
		void set_value(VALUE value) { this.value = value; }
		void set_next_entry(Entry * entry) { this.next_entry = entry; }

};

template<typename K, typename V>
class HashTable
{
	private:
		int N;
		Entry<K,V> **hash_table; //Make sure you understand this line

	public:
		HashTable()
		{
			this->N = 10000;
			hash_table = new Entry<K, V> * [this->N];

            		for (int i = 0; i < this->N; i++)
				hash_table[i] = NULL;
		}

		HashTable(int N)
		{
			this->N = N;
           	 	hash_table = new Entry<K, V> * [this->N];

            		for (int i = 0; i < this->N; i++)
				hash_table[i] = NULL;
		}

		/* hashcose string to int */
		int hashcode(string s);

		/* hashcode int to int */
		int hashcode(int i);

		/* hascode char to int */
		int hashcode(char c);

		/* hascode long to int */
		int hashcode(unsigned long ul);

		/* basic compression function */
		int compression(int hc);

		/* insert e into hash table */
		void insert(Entry<K, V> * e);

		/* replace e1 with e2 */
		void replace(Entry<K, V> * e1, Entry<K, V> * e2);

		/* find e and return */
		Entry<K, V> * find(Entry<K, V> * e);

		/* remove e from the table */
 		void remove(Entry<K, V> * e);

		/* if grow = 1 increase the table
 		 * otherwise decrease the table
 		 */
		void resize(bool grow);

		double compute_load_factor();

		int longest_chain_length();
};
template<typename K, typename V>
int HashTable<K, V>::hashcode(string s)
{
	unsigned long hash = 5381;
	for (size_t i = 0; i < s.size(); ++i)
	{
		hash = 33 * hash + (unsigned char)s[i];
	}
	return hash;
}
template<typename K, typename V>
int HashTable<K, V>::hashcode(int i)
{

}
template<typename K, typename V>
int HashTable<K, V>::hashcode(char c)
{

}
template<typename K, typename V>
int HashTable<K, V>::hashcode(unsigned long u1)
{

}
template<typename K, typename V>
int HashTable<K, V>::compression(int hc)
{

}
template<typename K, typename V>
void HashTable<K, V>::insert(Entry<K, V> * e)
{

}
template<typename K, typename V>
void HashTable<K, V>::replace(Entry<K, V> * e1, Entry<K, V> * e2)
{

}
template<typename K, typename V>
void HashTable<K, V>::remove(Entry<K, V> * e)
{

}
template<typename K, typename V>
void HashTable<K, V>::resize(bool grow)
{

}
template<typename K, typename V>
double HashTable<K, V>::compute_load_factor()
{

}
template<typename K, typename V>
int HashTable<K, V>::longest_chain_length()
{

}


/* I recommend you make a temp main for testing all of your boundary
 * cases.  I reserve the right to change the main function.  I promise
 * it will only call the function prototypes provided; which means, you
 * cannot change the prototypes.
 */
int main()
{
	//seed the random number generator
	srand(42);
	int menu_choice;
	do
	{
		HashTable<unsigned long, string> table_01(10000);
		unsigned long key;
		string value;
		Entry<unsigned long, string> * e;

		// Fill the table with random entries
		for (int i = 0; i < 10000; i++)
		{
			/* create a random entry */
			key = (sizeof(int) < sizeof(long)) ? (static_cast<int>(((unsigned long)rand()) << (sizeof(int) * 8)) | rand()) : rand();
			value = "";
			for (int j = 0; j < (rand() % 45 + 1); j++)
				value += 'a' + rand() % 26;
			cout << "Value " << i << " has been created. " << endl;
			e = new Entry<unsigned long, string>(key, value);
			cout << value << endl;
			//table_01.insert(e);
		}
		print_menu();
		cin >> menu_choice;
		while (menu_choice < 0 && menu_choice > 1)
		{
			cout << "Error: invalid input, try again: ";
			cin >> menu_choice;
		}
		if (menu_choice == 1)
		{
			template<typename K, typename V>
			HashTable<K, V>.hashcode(s);
		}
		//cout << "Longest Chain: " << table_01.longest_chain_length() << endl;
		//cout << "Load Factor: " << table_01.compute_load_factor() << endl;
	} while (menu_choice != 0);
	return 0;
}
void print_menu()
{
	cout << "1. View hash codes of converted strings " << endl;
	cout << "2. View hash codes of converted ints " << endl;
	cout << "3. View hash codes of converted characters " << endl;
	cout << "4. View hash codes of converted longs " << endl;
	cout << "5. Insert element into hash table" << endl;
	cout << "6. Replace element 1 with element 2" << endl;
	cout << "7. Search for an element and return it" << endl;
	cout << "8. Remove an element from the table" << endl;
	cout << "9. Compute the load factor" << endl;
	cout << "10. Returns the value of the longest chain in the table" << endl;
	cout << "11." << endl;
	cout << "12." << endl;
	cout << "0. Exit the program " << endl;
}

Если у меня есть такая проблема (которую я бы хотел избежать в первую очередь, изменив весь код кода), я мог бы попытаться сделать что-то вроде этого:

template<typename E>
void TryAndCatch(
    std::function<void (void)> tried,
    std::function<void (const E&) catched>
) {
    try {
        tried();
    } catch (const E& exception) {
        catched(exception);
    }
}

и затем используйте его следующим образом:

TryAndCatch<Stack<int>::Range>(
    []() {
        // tried code in lambda expression
    },
    [](const Stack<int>::Range& exception) {
        // catch code
    }
);

Но просто взглянув на это, я настоятельно рекомендовал бы переписать код, чтобы мне не нужно было его использовать, например, например, @Spook.

Обратите внимание, что шаблон должен быть создан таким образом, чтобы либо вы выбрали исключение, которое вы ловите, а затем используете шаблоны, чтобы каким-то образом помочь вам (возможно, обернуть код в каком-либо классе шаблонов, который будет обрабатывать их?) Или обеспечить некоторый общий знаменатель — интерфейс, абстрактную базу класс, ваш выбор.

04-30-2013


#1

Nurlana is offline


just started learning


Standalone sort function for the class

Hi, guys Could you please help with one more question? I need to write a standalone sort function, which will take a linked list parameter and sorts it. The function is included in the main list class as friend class:

Code:

friend void sort (UList<T>&)

I need to submit separate SortIS.h file for insertion sort. Here is my code:

Code:

#include <iostream>
 
template <class T>
void SortIS(UList<T>& list)
{
   T temp;
   for (int i=1; i<list.size(); i++)
   {
      temp = list[i];
      int j = i;
      while ((j>0)&&(list[j-1]>temp))
      {
         list[j] = list[j-1];
         j= j-1;
      }
      list[j] = temp;
   }
}

But the teacher said it didn’t compile returning an error: «undefined reference to `void». What I am missing here? Thanks in advance


Forum Updated on Feb 6th

This topic has been deleted. Only users with topic management privileges can see it.

  • Hi,
    I have a class which uses QTCPSocket. I create a tcp socket and connect the error signal to a slot in my class. All works fine, but no error() is emitted. The code is very simple, in the constructor I typed:

    m_socket = new QTcpSocket(this);
    connect(m_socket, &QTcpSocket::connected, this, &myTCPSocket::connected);
    connect(m_socket, &QTcpSocket::disconnected, this, &myTCPSocket::disconnected);
    connect(m_socket, &QTcpSocket::readyRead, this, &myTCPSocket::readyRead);
    connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
    

    and this is my error SLOT:

    void myTCPSocket::error(QAbstractSocket::SocketError socketError)
    {
        qDebug() << socketError;
    }
    

    I have never seen the error signal emitted. Is there something other to do?

  • It looks correct. If there is a problem with the signal-slot connection, you should check your debug output window, where Qt will report any problems.

    EDIT:
    Have you registered QAbstractSocket::SocketError as a metatype?

  • @kshegunov

    It looks correct. If there is a problem with the signal-slot connection, you should check your debug output window, where Qt will report any problems.
    

    I know what you’re talking about, but this time there are no warning in the debug window.

    Have you registered QAbstractSocket::SocketError as a metatype?
    

    mmm, this sounds new to me. Please, would you explain a but more? Why I should registed QAbstractSocket::SocketError? Isn’t it just an enum?

  • @Mark81
    Checkout in the documentation above the note. I could not believe it, but @kshegunov is right.

  • @koahnig
    Yeah, I see. I wonder why, though.
    Anyway, I added the following lines to my code:

    Q_DECLARE_METATYPE(QAbstractSocket::SocketError)
    qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
    

    But it returns this error:

    error: a template declaration cannot appear at block scope
    

    So I moved the Q_DECLARE_METATYPE line outside the class. Now I get:

    redefinition of 'struct QMetaTypeId<QAbstractSocket::SocketError>'
    

    I’m reading the docs about Q_DECLARE_METATYPE, I’m sorry, but I cannot understand how to use it. I don’t see an example.
    Thank you

    EDIT:
    Another think I don’t understand. The docs says:

    QAbstractSocket::SocketError is not a registered metatype, so for queued connections, you will have to register it with Q_DECLARE_METATYPE() and qRegisterMetaType().
    
    

    but at the end of QAbstractSocket.h I see:

    Q_DECLARE_METATYPE(QAbstractSocket::SocketState)
    Q_DECLARE_METATYPE(QAbstractSocket::SocketError)
    

    So why I have to declare them another time?

  • I believe it goes like this:

    Q_DECLARE_METATYPE says that a type is recognized by the Qt type system but it doesn’t define the necessary code to do that. The necessary code has to be hooked into the Qt type system. Because the QtNetwork library is separate from the QtCore library, the QtCore library cannot define the necessary code because it would create a dependency on the QtNetwork library.

    So you have to register the code in your application if you want pass the types via signals and slots which is one important part of the Qt type system. Qt has to know how to pack and unpack types so that they can be marshaled and un-marshaled through the message queues.

    Even though the necessary registration could be done in the QtNetwork library in a library startup routine, I don’t think it is since the Qt networking classes can be used without signals and slots and an application doing that would not want all the Qt type system code pulled in.

  • @Mark81
    I had wondered about @kshegunov ‘s remark. Therefore, I looked it up and found the text section to my surprise.

    However, the «and» is wrong as far as I know, you should use either one but not both.
    qRegisterMetaType and Q_DECLARE_METATYPE .

    The other things is that you have mentioned that there has been no warning in a debug window, but you should see one when the type is not registered. Therefore, try again without registration and if there is a warning.
    Since you checked already the header file and a declaration is there, this is pointing towards a bug in documentation.

    And you are right another declaration shall not be required then.

    However, coming back top your initial problem. Just to be sure. Did you check with an error condition?

  • @Mark81
    Actually you’ll probably need only Q_DECLARE_METATYPE as this is done at compile time — exposing the type to the metatype system (I know it is an enum but it’s needed for the QVariant and the like). qRegisterMetaType you’ll need if creating objects by class name dynamically, and it seems for queued connections, generally you won’t need to call that function, but I suggest you do.

    @koahnig
    Directly from the documentation: «Adding a Q_DECLARE_METATYPE() makes the type known to all template based functions, including QVariant. Note that if you intend to use the type in queued signal and slot connections or in QObject’s property system, you also have to call qRegisterMetaType() since the names are resolved at runtime.»
    Sometimes you need both.

  • @koahnig
    It would be interesting to know when the Q_DECLARE_METATYPE lines at the bottom of QAbstractSocket.h were added. Perhaps the docs was not updated after that, so now it should look like: «QAbstractSocket::SocketError is a declared but not a registered metatype, so for queued connections, you will have to register it with qRegisterMetaType().»
    It’s weird no one else in the world has ever used this signal!

    Anyway, to test the error signal I’m simply trying to connect to my server (which works under normal conditions) with the Ethernet cable disconnected.

    I’m expecting at least one of the following errors:

    QAbstractSocket::ConnectionRefusedError	0	The connection was refused by the peer (or timed out).
    QAbstractSocket::HostNotFoundError	    2	The host address was not found.
    QAbstractSocket::SocketTimeoutError	    5	The socket operation timed out.
    QAbstractSocket::NetworkError	        7	An error occurred with the network (e.g., the network cable was accidentally plugged out).
    

    I also tried to connect before and then unplug the network cable. Nothing.

  • Oh dear! It works Even without qRegisterMetaType() — so the docs are definitely wrong.
    But it takes a huge time before fire, something about 30 s! This if I try to connect without the cable. After 30 seconds I get the NetworkError message.

    On the other hand, if I establish the connection and then I unplug the cable nothing happens, even after few minutes.
    Anyway I cannot wait for such a long time to inform the user the device is not connected anymore. I’m afraid I need to implement by myself a sort of software «ping» to be sure the remote device is still there. What a pity.

  • The default time out on QTcpSocket is 30s, you can reduce it if you want more responsive failure detection but you should be sure that you do not use a timeout less than normal round trip latency to the server.

    The docs are not wrong, you only need to register the types for Queued signal/slot connections as several have said above. Non-queued signal/slot connections are simply member function calls.

  • To add to @bsomervi there you have the default waiting time of 30 seconds

    @bsomervi said:

    The docs are not wrong, you only need to register the types for Queued signal/slot connections as several have said above. Non-queued signal/slot connections are simply member function calls.

    This is the first time I have seen such a difference for signal-slot connections. However, certainly I know only a small fraction of the documentation.
    If you say so, I assume that you are correct about different behaviour for queued and non-queued connections.
    The documentation is at least a bit ambiguous in that respect and the sentences might require a revision for clarity.

  • @koahnig said:

    This is the first time I have seen such a difference for signal-slot connections.

    It pops out every time you write a class that you intent to use as a signal/slot parameter in multithreaded application.

  • @kshegunov

    That there is a difference between queued and non-queued is clear.
    I had meant that there is difference in registered objects between queued and non-queued connections.
    I came across the need to register for my own classes. So far I thought that all Qt classes are registered alreay. Thought to have read a reference somewhere, but also quite a while ago.

  • @bsomervi

    The default time out on QTcpSocket is 30s, you can reduce it if you want more responsive failure detection
    

    English is not my primary language, thus I apologize if sometimes it’s hard to understand what I’m reading. Anyway I read through the docs and I cannot find how to reduce this timeout. As @koahnig said I could use the waitForConnected() function but: 1. the docs say it may fail randomly on Windows, 2. it blocks the execution of my code, 3. it could work only during connection, but it isn’t useful to detect a failure (i.e. the cable disconnected after).

    I cannot find a method like: setTimeout() or similar.

    Currently the only way I found is to periodically send back and forth a message: when I don’t receive the answer in few seconds I assume the connection is lost. I hate this approach, though! I’m pretty sure the system knows if a TCP socket isn’t alive anymore!

  • @Mark81 Sorry I have misled you, I was confusing the timeout on the wait…() functions with the asynchronous signals. You do not want the wait…() functions in the GUI thread as they block.

    The first thing to note is that normal TCP/IP will retry 12 times to send a data segment taking up to 9 minutes before it causes an error.

    I think you have two choices in the normal TCP/IP framework.

    If you are sending data and expecting a reply, you can start a single shot timer that is cancelled if the reply is received but causes your communications failed code to run when it times out.

    If you are just waiting for data then you will get no notification of errors as TCP/IP will wait forever on a disconnected circuit. So in this case you must have your server send you periodic «heartbeat» data to confirm its reachability.


Recommended Answers

You need to do some research on Templates. This clearly would not work in main because there is no way at run-time to determine what types are the variables. (In this example, anyway).

The correct thing would be to do the following:

#include <iostream>
#include <cstdlib>
#include …

Jump to Post

The construct template<typename T> is used to paramatrize classes, structs, unions, functions or, in C++ 11, type aliases with type parameters (or in some cases other compile-time parameters). So template<typename T> must be in front of the definitions of one of those things (like template<typename T> class …

Jump to Post

All 8 Replies

Member Avatar

9 Years Ago

declare your template outside the main() function and then try to compile it. hope it helps.! thanks.

Member Avatar


phorce

131



Posting Whiz in Training



Featured Poster


9 Years Ago

You need to do some research on Templates. This clearly would not work in main because there is no way at run-time to determine what types are the variables. (In this example, anyway).

The correct thing would be to do the following:

#include <iostream>
#include <cstdlib>
#include <string>


using namespace std;

template<typename T>
T declareVariable(T theVariable)
{
    T temp = theVariable;

    return temp;
}
int main()
{
    string value = declareVariable<string>("hello");

    cout << value;
}

Notice how in main I can now allow for the variable to be declared so the compiler knows at run time?

I can therefore do this for an interger as well:

int value2 = declareVariable<int>(123);

This should be the solution :)

Member Avatar


sepp2k

378



Practically a Master Poster


9 Years Ago

The construct template<typename T> is used to paramatrize classes, structs, unions, functions or, in C++ 11, type aliases with type parameters (or in some cases other compile-time parameters). So template<typename T> must be in front of the definitions of one of those things (like template<typename T> class Foo {...}). In your case it’s inside a function body, which is not allowed.

It’s not clear what you want parametrize here. If you wanted to parametrize main, you’d need to write template<typename T> int main(), except that it’s not legal for main to be a template function because main is called by the operating system and the OS would not know which type to supply as an argument.

So you’d need to define your own function template<typename T> mymain(), put the code in there and then call that from main with the appropriate type argument. Except that won’t work either because:

T one = "test";
T two = 255;
T three = 287.52;
T four = 'x';

Those four variables can’t have the same type (unless there’s a custom defined class with implicit constructors accepting each of the four types, but in your code there’s not).

It’s important to understand that in any given instantiation of a template, all occurrences of T refer to the same type. So if call, say mymain<int>() and mymain contains the above code, it will behave like you wrote:

int one = "test";
int two = 255;
int three = 287.52;
int four = 'x';

And this won’t compile because you can’t assign a string literal (or any other type of pointer) to an integer like that. Likewise mymain<char*> or mymain<string> wouldn’t work because the other values can’t be assigned to a string.

Member Avatar

9 Years Ago

Thanks for the answers.. I understand now.
phorce, I’ve used your example without indicating the type next to the function call. By using the function you provided and calling it like the below: It works fine.

cout << myfunction(20) << endl;
cout << myfunction("TestString") << endl;
cout << myfunction(2.1) << endl;
cout << myfunction('x') << endl;

Member Avatar

9 Years Ago

Click Here

This is a great link which will give you idea that how exactly templates work. It will be beneficial for you. hope it helps! thanks. :)

Member Avatar

Member Avatar


phorce

131



Posting Whiz in Training



Featured Poster


9 Years Ago

@christinetom — That’s great! The compiler will specify the type based on the type of variable passed through. Good luck and thanks for marking this as solved :)

Edited

9 Years Ago
by phorce

Member Avatar

9 Years Ago

As others told, you should define template outside the main function, hope that works.


Reply to this topic

Be a part of the DaniWeb community

We’re a friendly, industry-focused community of developers, IT pros, digital marketers,
and technology enthusiasts meeting, networking, learning, and sharing knowledge.

32 / 30 / 4

Регистрация: 01.02.2014

Сообщений: 877

1

Как передать структуру через сигнал?

06.10.2015, 16:43. Показов 3499. Ответов 17


Сабж в теме, я так понял нужно воспользоватся функцией qRegisterMetaType, но чёт не пойму как ею пользоватся

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



ArmanPrestige

Pied Piper

236 / 227 / 57

Регистрация: 15.01.2013

Сообщений: 855

06.10.2015, 17:07

2

А что непонятного?

C++ (Qt)
1
qRegisterMetaType<MyClass>("MyClass");



0



32 / 30 / 4

Регистрация: 01.02.2014

Сообщений: 877

06.10.2015, 17:20

 [ТС]

3

пишет оштбку
specializing member ‘::qRegisterMetaType<ResultData>’ requires ‘template<>’ syntax

Добавлено через 11 минут
а, всё, понял, написал qRegisterMetaType в main и всё заработало



0



Диссидент

Эксперт C

27209 / 16962 / 3749

Регистрация: 24.12.2010

Сообщений: 38,147

06.10.2015, 19:43

4

mh-coder, Как альтернатива, передавать void *. Нет?



0



86 / 45 / 11

Регистрация: 20.12.2010

Сообщений: 216

Записей в блоге: 1

09.10.2015, 10:36

5

mh-coder, Байт, насколько я помню есть у кьюти такой класс как QPointer, который можно использовать не хуже void*
P.S. хотя сам чаще void* использую ^_^



0



Kurles

161 / 126 / 30

Регистрация: 30.05.2015

Сообщений: 380

09.10.2015, 10:51

6

Цитата
Сообщение от mh-coder
Посмотреть сообщение

Сабж в теме, я так понял нужно воспользоватся функцией qRegisterMetaType, но чёт не пойму как ею пользоватся

a после объявления структуры

C++ (Qt)
1
Q_DECLARE_METATYPE(MyStruct)

делал?



0



Диссидент

Эксперт C

27209 / 16962 / 3749

Регистрация: 24.12.2010

Сообщений: 38,147

09.10.2015, 11:34

7

Цитата
Сообщение от Skjame
Посмотреть сообщение

есть у кьюти такой класс как QPointer, который можно использовать не хуже void*

Да, конечно. Моя идея была в том, чтобы передавать нечто обезличенное, и разбираться с ним уже внутри слота.



0



32 / 30 / 4

Регистрация: 01.02.2014

Сообщений: 877

10.10.2015, 20:12

 [ТС]

8

Цитата
Сообщение от Kurles
Посмотреть сообщение

a после объявления структуры Код C++ (QT)Выделить код1
Q_DECLARE_METATYPE(MyStruct) делал?

нет, а зачем?



0



161 / 126 / 30

Регистрация: 30.05.2015

Сообщений: 380

12.10.2015, 16:16

9

Adding a Q_DECLARE_METATYPE() makes the type known to all template based functions, including QVariant. Note that if you intend to use the type in queued signal and slot connections or in QObject’s property system, you also have to call qRegisterMetaType() since the names are resolved at runtime.

.
Хочешь структуру использовать в качестве параметра сигнала в «queued signal and slot connections», будь добр кроме регистрации типа через функцию qRegisterMetaType так же объвить его через вышеназванный макрос.



0



mh-coder

32 / 30 / 4

Регистрация: 01.02.2014

Сообщений: 877

12.10.2015, 19:53

 [ТС]

10

Цитата
Сообщение от Kurles
Посмотреть сообщение

Хочешь структуру использовать в качестве параметра сигнала в «queued signal and slot connections», будь добр кроме регистрации типа через функцию qRegisterMetaType так же объвить его через вышеназванный макрос.

без макроса работает, добавил его, стала вылетать ошибка

C++ (Qt)
1
2
3
C:QtQtMgw5.5mingw492_32includeQtCoreqmetatype.h:1843: ошибка: a template declaration cannot appear at block scope
     template <>                                                         
     ^



0



161 / 126 / 30

Регистрация: 30.05.2015

Сообщений: 380

14.10.2015, 10:11

11

Покажи полностью проблемный код.



1



Pied Piper

236 / 227 / 57

Регистрация: 15.01.2013

Сообщений: 855

14.10.2015, 11:47

12

mh-coder, судя по ошибке не туда впихнули макрос.



1



32 / 30 / 4

Регистрация: 01.02.2014

Сообщений: 877

29.10.2015, 19:02

 [ТС]

13

Цитата
Сообщение от ArmanPrestige
Посмотреть сообщение

судя по ошибке не туда впихнули макрос.

а куда надо?



0



Pied Piper

236 / 227 / 57

Регистрация: 15.01.2013

Сообщений: 855

29.10.2015, 19:10

14

mh-coder, код покажите



1



32 / 30 / 4

Регистрация: 01.02.2014

Сообщений: 877

29.10.2015, 19:43

 [ТС]

15

Цитата
Сообщение от ArmanPrestige
Посмотреть сообщение

код покажите

кода там много, короче потыкал в разные места, и нашел, нужно было его влепить сразу после создания структуры, всем спасибо



0



2 / 2 / 1

Регистрация: 20.01.2015

Сообщений: 100

25.02.2019, 15:57

16

Ну , что за человек — задал вопрос, а решение не дал в конечном итоге. Хотя бы показал бы, как проблему решил.



0



308 / 168 / 46

Регистрация: 18.10.2017

Сообщений: 1,585

25.02.2019, 20:48

17

Там ещё надо подключать
#include <QMetatType>



0



0 / 0 / 0

Регистрация: 19.05.2018

Сообщений: 14

25.02.2019, 23:56

18

используй void* и кастуй его к нужному типу когда понадобится



0



Понравилась статья? Поделить с друзьями:

Читайте также:

  • Error a redistributable package easyanticheat was not installed successfully
  • Error a pointer to a bound function may only be used to call the function
  • Error a network error occurred vmware horizon client
  • Error a malformed block was encountered while loading a block
  • Error a jnl error has occurred please check your installation and try again майнкрафт

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии