2011-10-04 5 views
5

Ideoneテストケース:http://ideone.com/lzepFキャストは、定数式では使用できません

コード:

#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; 
} 

エラー:

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 

当方は一切の行番号を持っていないので、: (それは最初のwrite(s, x)について文句を言って、私にはreinterpret_cast<const char*>(const unsigned int*)について文句を言うようですが、私はそれが法的でなければならないと確信しています。

どうなりますか?

+1

'std :: is_pointer ()'などの代わりに、 'std :: is_pointer :: value'であってはいけませんか? –

答えて

5

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); 
+0

回線番号が少しオフになっていますか?それが起こると嫌い.. –

+0

@ TomalakGeret'kal、ええそれはちょっとねじれている... – Nim

+0

おかしい、gcc-4.6.1でうまくいく。ありがとう! – Nick

1

C++ 03標準5.19 "定数式"、パラ1つの状態:

C++には、配列境界(8.3.4,5.3.4)として、case式(6.4.2)として、ビットフィールド長(9.6)として、または列挙型定数として評価される式が必要です。列挙子i (7.2)、静的メンバーイニシャライザ(9.4.2)、および整数型または列挙型の非型テンプレート引数(14.3)として定義されています。

定数式:条件付き表現

整数定数式は(8.5)のみリテラル(2.13)、列挙子、constの変数または定数式で初期化された整数または列挙型の静的データメンバを含むことができます、整数型または列挙型の非型テンプレートパラメータ、および式のsizeofが含まれます。浮動小数点数(2.13.3)は、整数型または列挙型にキャストされている場合にのみ表示されます。 整数型または列挙型への型変換のみ使用できます。特に、sizeof式を除き、関数、クラスオブジェクト、ポインタ、または参照は使用されず、代入、インクリメント、デクリメント、ファンクションコール、またはカンマ演算子は使用されないものとします。

コード文:

static_assert(STD :: is_pointer()、 "それはポインタだ、あなたはおそらくそれを書きたくありません"!)。 static_assert(std :: is_pod()、 "これはPODではありません:書き込めません");

この規則を破ると、コンパイラは不平を言います。

+0

これはC++ 11でも当てはまりますか? OPは、新しい 'g ++'に元のコードで成功を報告します。 –

+0

@ TomalakGeret'kal:C++ 11のドラフトとゲットバックを見てみましょう。 –

+0

@ TomalakGeret'kal:これはC++ 11で変更されました。標準ではこの制約が課されなくなりました。gccはC++ 11に準拠するのに十分速いと思われます。 –

関連する問題