Hello,

J'ai dans mon code une requête une structure Request avec plusieurs champs dont un qui s'appelle Type. En fonction de ce type, l'exécution de la requête utilise les autres champs de manière appropriée.

En lisant des trucs sur std::variant hier, j'ai fait un code d'essai très concluant. Le code complet donne ceci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
#include <cassert>
#include <cstdint>
#include <variant>
 
struct ReadRequest {
	ReadRequest(std::uint8_t* data, std::size_t length) :
			data(data),
			length(length) {
		assert(data != nullptr);
	}
 
	std::uint8_t* const data;
	const std::size_t length;
};
 
struct WriteRequest {
	WriteRequest(std::uint8_t* data, std::size_t length) :
			data(data),
			length(length) {
		assert(data != nullptr);
	}
 
	const std::uint8_t* const data;
	const std::size_t length;
};
 
struct DoubleWriteRequest {
	DoubleWriteRequest(const std::uint8_t* data_first, std::size_t length_first,
			   const std::uint8_t* data_second, std::size_t length_second) :
			data_first(data_first),
			length_first(length_first),
			data_second(data_second),
			length_second(length_second) {
		assert(data_first != nullptr);
		assert(data_second != nullptr);
	}
 
	const std::uint8_t* const data_first;
	const std::size_t length_first;
	const std::uint8_t* const data_second;
	const std::size_t length_second;
};
 
using Request = std::variant<ReadRequest, WriteRequest, DoubleWriteRequest>;
 
//---------------------------------------------------
#include "Request.hpp"
 
extern "C" {
void spi_driver_read(std::uint8_t* data, std::size_t length);
void spi_driver_write(const std::uint8_t* data, std::size_t length);
}
 
class SpiBus {
public:
	void execute(const Request& request) {
		std::visit(requestProcessor_m, request);
	}
 
private:
	class RequestProcessor {
	public:
		void operator()(const ReadRequest& rr) {
			spi_driver_read(rr.data, rr.length);
		}
 
		void operator()(const WriteRequest& wr) {
			spi_driver_write(wr.data, wr.length);
		}
 
		void operator()(const DoubleWriteRequest& dwr) {
			spi_driver_write(dwr.data_first, dwr.length_first);
			spi_driver_write(dwr.data_first, dwr.length_second);
		}
	};
 
	RequestProcessor requestProcessor_m;
};
 
//---------------------------------------------------
#include <array>
#include "SpiBus.hpp"
 
int main() {
	SpiBus bus;
	std::array<std::uint8_t, 15> buffer;
 
	ReadRequest rr{buffer.data(), buffer.size()};
	bus.execute(rr);
 
//	ReadRequest bad_rr{nullptr, 42}; // triggers assert()
 
	WriteRequest wr{buffer.data(), buffer.size()};
	bus.execute(wr);
 
	DoubleWriteRequest dwr{buffer.data(), buffer.size(), buffer.data(), buffer.size()};
	bus.execute(dwr);
}
Il s'avère que ma structure Request actuelle (pas celle avec std::variant) possède un champ privé, un sémaphore, pour des besoins de synchronisation. Il est privé et accessible uniquement par la classe SpiBus qui est une amie. Pour avoir la même chose avec std::variant sans avoir à mettre ce champ dans toutes mes variantes, je me suis dit que je pourrais faire ça :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
using RequestVariant = std::variant<ReadRequest, WriteRequest, DoubleWriteRequest>;
 
struct Request : public RequestVariant {
private:
	int semaphore; // type bidon
};
Sauf que ça ne fait pas de chocapic.... J'ai dû rajouter des constructeurs :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct Request : public RequestVariant {
	Request(ReadRequest& request) :
			RequestVariant(request) {
	}
 
	Request(WriteRequest& request) :
			RequestVariant(request) {
	}
 
	Request(DoubleWriteRequest& request) :
			RequestVariant(request) {
	}
 
private:
	int semaphore; // type bidon
};
Et mon std::visit ne compile pas, avec comme pour tout template un peu avancé un message d'erreur à rallonge, mais qui je pense se résume à ça :
error: invalid use of incomplete type 'struct std::variant_size<Request>'
struct variant_size<const _Variant> : variant_size<_Variant> {};
Bref, comment feriez-vous ?

Merci d'avance