Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cast to integral type or other type cannot appear in a constant expression

Tags:

c++

Ideone testcase: http://ideone.com/lzepF

Code:

#include <iostream>
#include <sstream>
#include <vector>
#include <map>
#include <list>
#include <set>

#include <stdint.h>

template <typename T> std::ostream& write(std::ostream& os, T const& x);
template <typename T> std::istream& read(std::istream& is, T& x);

template <typename T, typename U> std::ostream& write(std::ostream& os, std::pair<T, U> const& rh);
template <typename T, typename U> std::istream& read(std::istream& is, std::pair<T, U>& rh);

template <typename T> std::ostream& writeContainer(std::ostream& os, T const& rh);

template <typename T, typename U> std::ostream& write(std::ostream& os, std::map<T, U> const& rh);
template <typename T, typename U> std::istream& read(std::istream& is, std::map<T, U> rh);

template <typename T> std::ostream& write(std::ostream& os, std::vector<T> const& rh);
template <typename T> std::istream& read(std::istream& is, std::vector<T>& rh);

template <typename T>
std::ostream& write(std::ostream& os, T const& 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 *>(&x), sizeof(T));
    return os;
}

template <typename T>
std::istream& read(std::istream& is, T& 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 *>(&x), sizeof(T));
    return is;
}

template <typename T, typename U>
std::ostream& write(std::ostream& os, std::pair<T, U> const& rh){
    write(os, rh.first);
    write(os, rh.second);
    return os;
}

template <typename T, typename U>
std::istream& read(std::istream& is, std::pair<T, U>& rh){
    read(is, rh.first);
    read(is, rh.second);
    return is;
}

template <typename T>
std::ostream& writeContainer(std::ostream& os, T const& 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::istream& readContainer(std::istream& is, T& 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::ostream& write(std::ostream& os, std::map<T, U> const& rh){
    return writeContainer(os, rh);
}

template <typename T, typename U>
std::istream& read(std::istream& is, std::map<T, U> rh){
    return readContainer(is, rh);
}

template <typename T>
std::ostream& write(std::ostream& os, std::vector<T> const& rh){
    return writeContainer(os, rh);
}

template <typename T>
std::istream& read(std::istream& is, std::vector<T>& 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;
}

Errors:

prog.cpp: In function 'std::ostream& write(std::ostream&, const T&) [with T = unsigned int, std::ostream = std::basic_ostream<char>]':
prog.cpp:57:2:   instantiated from 'std::ostream& writeContainer(std::ostream&, const T&) [with T = std::vector<int>, std::ostream = std::basic_ostream<char>]'
prog.cpp:92:30:   instantiated from 'std::ostream& write(std::ostream&, const std::vector<T>&) [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::ostream& write(std::ostream&, const T&) [with T = int, std::ostream = std::basic_ostream<char>]':
prog.cpp:60:3:   instantiated from 'std::ostream& writeContainer(std::ostream&, const T&) [with T = std::vector<int>, std::ostream = std::basic_ostream<char>]'
prog.cpp:92:30:   instantiated from 'std::ostream& write(std::ostream&, const std::vector<T>&) [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

Since we have no line numbers, :( , it complains about the FIRST write(s, x), and seems to me complain about the reinterpret_cast<const char*>(const unsigned int*) but I'm pretty sure that should be legal.

What's going wrong?

like image 478
Nick Avatar asked Oct 04 '11 16:10

Nick


2 Answers

You are using the is_pod and is_pointer incorrectly. You need to change it to the following:

    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");

You can test with this:

    write(std::cout, 1);
    int *p = 0;
    write(std::cout, p);
like image 153
Nim Avatar answered Nov 18 '22 18:11

Nim


C++03 Standard 5.19 "Constant expressions", Para 1 states:

In several places, C++ requires expressions that evaluate to an integral or enumeration constant: as array bounds (8.3.4, 5.3.4), as case expressions (6.4.2), as bit-field lengths (9.6), as enumerator initializers (7.2), as static member initializers (9.4.2), and as integral or enumeration non-type template arguments (14.3).

constant-expression: conditional-expression

An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, and sizeof expressions. Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types. Only type conversions to integral or enumeration types can be used. In particular, except in sizeof expressions, functions, class objects, pointers, or references shall not be used, and assignment, increment, decrement, function-call, or comma operators shall not be used.

The code statements:

static_assert(!std::is_pointer(), "That's a pointer, you probably don't want to write that"); static_assert(std::is_pod(), "That's not a POD: can't write it");

break this rule and hence the compiler complains.

like image 32
Alok Save Avatar answered Nov 18 '22 17:11

Alok Save