#c
#c
Вопрос:
Ideone testcase: http://ideone.com/lzepF
Код:
#include <iostream>
#include <sstream>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <stdint.h>
template <typename T> std::ostreamamp; write(std::ostreamamp; os, T constamp; x);
template <typename T> std::istreamamp; read(std::istreamamp; is, Tamp; x);
template <typename T, typename U> std::ostreamamp; write(std::ostreamamp; os, std::pair<T, U> constamp; rh);
template <typename T, typename U> std::istreamamp; read(std::istreamamp; is, std::pair<T, U>amp; rh);
template <typename T> std::ostreamamp; writeContainer(std::ostreamamp; os, T constamp; rh);
template <typename T, typename U> std::ostreamamp; write(std::ostreamamp; os, std::map<T, U> constamp; rh);
template <typename T, typename U> std::istreamamp; read(std::istreamamp; is, std::map<T, U> rh);
template <typename T> std::ostreamamp; write(std::ostreamamp; os, std::vector<T> constamp; rh);
template <typename T> std::istreamamp; read(std::istreamamp; is, std::vector<T>amp; rh);
template <typename T>
std::ostreamamp; write(std::ostreamamp; os, T constamp; x){
static_assert(!std::is_pointer<T>(), "That's a pointer, you probably don't want to write that");
static_assert(std::is_pod<T>(), "That's not a POD: can't write it");
os.write(reinterpret_cast<const char *>(amp;x), sizeof(T));
return os;
}
template <typename T>
std::istreamamp; read(std::istreamamp; is, Tamp; x){
static_assert(!std::is_pointer<T>(), "That's a pointer, you probably don't want to read that");
static_assert(std::is_pod<T>(), "That's not a POD: can't read it");
is.read(reinterpret_cast<char *>(amp;x), sizeof(T));
return is;
}
template <typename T, typename U>
std::ostreamamp; write(std::ostreamamp; os, std::pair<T, U> constamp; rh){
write(os, rh.first);
write(os, rh.second);
return os;
}
template <typename T, typename U>
std::istreamamp; read(std::istreamamp; is, std::pair<T, U>amp; rh){
read(is, rh.first);
read(is, rh.second);
return is;
}
template <typename T>
std::ostreamamp; writeContainer(std::ostreamamp; os, T constamp; rh){
uint32_t size = std::distance(rh.begin(), rh.end());
write(os, size);
for(auto it = rh.begin(); it != rh.end(); it){
write(os, *it);
}
return os;
}
template <typename T>
std::istreamamp; readContainer(std::istreamamp; is, Tamp; rh){
uint32_t size;
read(is, size);
std::insert_iterator<T> it(rh, rh.end());
for(uint32_t i=0; i<size; i) {
typename T::value_type x;
read(is, x);
it = x;
}
return is;
}
template <typename T, typename U>
std::ostreamamp; write(std::ostreamamp; os, std::map<T, U> constamp; rh){
return writeContainer(os, rh);
}
template <typename T, typename U>
std::istreamamp; read(std::istreamamp; is, std::map<T, U> rh){
return readContainer(is, rh);
}
template <typename T>
std::ostreamamp; write(std::ostreamamp; os, std::vector<T> constamp; rh){
return writeContainer(os, rh);
}
template <typename T>
std::istreamamp; read(std::istreamamp; is, std::vector<T>amp; rh){
return readContainer(is, rh);
}
int main(){
{
std::stringstream s;
std::vector<int> x = {0, 1, 2, 3};
write(s, x);
}
{
std::stringstream s;
std::map<int, int> x = {{0, 0}, {1, 2}, {2, 4}, {3, 6}};
write(s, x);
}
return 0;
}
Ошибки:
prog.cpp: In function 'std::ostreamamp; write(std::ostreamamp;, const Tamp;) [with T = unsigned int, std::ostream = std::basic_ostream<char>]':
prog.cpp:57:2: instantiated from 'std::ostreamamp; writeContainer(std::ostreamamp;, const Tamp;) [with T = std::vector<int>, std::ostream = std::basic_ostream<char>]'
prog.cpp:92:30: instantiated from 'std::ostreamamp; write(std::ostreamamp;, const std::vector<T>amp;) [with T = int, std::ostream = std::basic_ostream<char>]'
prog.cpp:104:13: instantiated from here
prog.cpp:29:11: error: a cast to a type other than an integral or enumeration type cannot appear in a constant-expression
prog.cpp:29:11: error: a cast to a type other than an integral or enumeration type cannot appear in a constant-expression
prog.cpp: In function 'std::ostreamamp; write(std::ostreamamp;, const Tamp;) [with T = int, std::ostream = std::basic_ostream<char>]':
prog.cpp:60:3: instantiated from 'std::ostreamamp; writeContainer(std::ostreamamp;, const Tamp;) [with T = std::vector<int>, std::ostream = std::basic_ostream<char>]'
prog.cpp:92:30: instantiated from 'std::ostreamamp; write(std::ostreamamp;, const std::vector<T>amp;) [with T = int, std::ostream = std::basic_ostream<char>]'
prog.cpp:104:13: instantiated from here
prog.cpp:29:11: error: a cast to a type other than an integral or enumeration type cannot appear in a constant-expression
prog.cpp:29:11: error: a cast to a type other than an integral or enumeration type cannot appear in a constant-expression
Поскольку у нас нет номеров строк, 🙁 , он жалуется на ПЕРВОЕ write(s, x)
и, как мне кажется, жалуется на reinterpret_cast<const char*>(const unsigned int*)
, но я уверен, что это должно быть законно.
Что происходит не так?
Комментарии:
1. Вместо
std::is_pointer<T>()
etc., не так лиstd::is_pointer<T>::value
?
Ответ №1:
Вы is_pod
is_pointer
неправильно используете и . Вам необходимо изменить его на следующее:
static_assert(!std::is_pointer<T>::value, "That's a pointer, you probably don't want to write that");
static_assert(std::is_pod<T>::value, "That's not a POD: can't write it");
Вы можете протестировать с помощью этого:
write(std::cout, 1);
int *p = 0;
write(std::cout, p);
Ответ №2:
C 03 Стандарт 5.19 «Константные выражения», пункт 1 гласит:
В нескольких местах C требует выражений, которые вычисляются до целочисленной или перечисляемой константы: как границы массива (8.3.4, 5.3.4), как выражения регистра (6.4.2), как длины битовых полей (9.6), как инициализаторы перечислителя (7.2), как инициализаторы статических элементов (9.4.2) и как целыеили перечисление нетиповых аргументов шаблона (14.3).
constant-expression: условное выражение
Целочисленное константное выражение может включать в себя только литералы (2.13), перечислители, переменные const или статические элементы данных целочисленных или перечисляемых типов, инициализированные константными выражениями (8.5), нетиповые шаблонные параметры целочисленных или перечисляемых типов и выражения sizeof. Плавающие литералы (2.13.3) могут появляться, только если они приведены к целочисленным или перечислительным типам. Можно использовать только преобразования типов в целочисленные или перечисляемые типы.В частности, за исключением выражений sizeof, не должны использоваться функции, объекты класса, указатели или ссылки, а также не должны использоваться операторы присваивания, увеличения, уменьшения, вызова функции или запятой.
Операторы кода:
static_assert(!std::is_pointer(), «Это указатель, вы, вероятно, не хотите его записывать»); static_assert(std::is_pod(), «Это не POD: не могу его записать»);
нарушите это правило, и, следовательно, компилятор пожалуется.
Комментарии:
1. Это все еще верно для C 11? OP сообщает об успешном выполнении исходного кода в более новой
g
версии .2. @Tomalakgeret’kal: Позвольте мне посмотреть черновик C 11 и получить ответ.
3. @Tomalakgeret’kal: Да, это изменено в C 11, стандарт больше не налагает этого ограничения, кажется, gcc был достаточно быстрым, чтобы соответствовать C 11.