2016-08-12 7 views
2

ここで私はいくつかの段階で必要な小さな研究をしています。const型のC++テンプレートの一般化

私はラインが

const char t[] = "ABC"; 

私が取得する<-- HEREをマーク変更した場合、次の

小さな例は今、この(http://coliru.stacked-crooked.com/a/75c29cddbe6d8ef6

#include <iostream> 

template <class T> 
class funny 
{ 
public: 
    funny(T& a) : v(a) {v -= 1; } 
    virtual ~funny() { v += 1; } 
    operator T() {return v;} 

private: 
    T& v; 
}; 

#define V(a) funny<decltype(a)>(a) 

int main() 
{ 
    char t[] = "ABC"; // <-- HERE 

    if(V(t[0]) == (char)'A') 
    { 
     std::cout << "Pass" << t[0]; 
    } 
    else 
    { 
     std::cout << "No Pass" << t[0]; 
    } 
} 

のようなものです、質問が来ますコンパイルエラー:

main.cpp: In instantiation of 'funny<T>::funny(T&) [with T = const char&]': 
main.cpp:21:7: required from here 
main.cpp:7:28: error: assignment of read-only location '((funny<const char&>*)this)->funny<const char&>::v' 
    funny(T& a) : v(a) {v -= 1; } 
         ~~^~~~ 
main.cpp: In instantiation of 'funny<T>::~funny() [with T = const char&]': 
main.cpp:21:7: required from here 
main.cpp:8:27: error: assignment of read-only location '((funny<const char&>*)this)->funny<const char&>::v' 
    virtual ~funny() { v += 1; } 
        ~~^~~~ 

私は定数を修正しようとしているので、これは完全に理解できます。コンパイラはここにあります。しかし、私は本当にこれがconstのデータのためにも動作する必要があるので、私は、テンプレートのconstの専門作成しようとしました:

template <class T> 
class funny <T const> 
{ 
public: 
    funny(const T& a) : v(a) {} 
    operator T() {return v;} 

private: 
    const T& v; 
}; 

しかしかかわらず、コンパイラは、それを見つけることはありませんが、まだ非をコンパイルしようとしますconstバージョン。

この問題を解決する方法はありますか?あなたが変更した場合

+2

をconstで修飾されていない( 'T'は' X 'で 'X'は' const char'です)。これは、 't [0]'が式であり、式としての左辺値であるためです。そのような式の 'decltype(e)'は左辺参照型を生成します。 – dyp

答えて

1

はコンパイル:

template <class T> 
class funny <T const> 

へ:あなたのconst char専門と一致していないconst char&

template <class T> 
class funny <const T&> 
+0

本当にあります:)ありがとう! – fritzone

+1

'decltype(t [0])'が参照であるため、これが機能することに注意してください。これは単に 'const char'のためにはうまくいかないでしょう。 @Milesの回答はより堅牢です。 – TartanLlama

+0

@TartanLlama私は同意します – marcinj

4

decltype(t[0])推論、。 2つのオプションがあります。

1)特殊化をtemplate <class T> class funny <T const&>に変更してください。これはこのケースでは機能しますが、const int FOO = 42; V(FOO);では機能しません。

2)常に非参照型に推定するあなたのVマクロを変更する:あなたは 'T'が参照され、 `のconstのchar&`、と推測され、エラーメッセージで見ることができるように

#define V(a) funny<typename std::remove_reference<decltype(a)>::type>(a) 
関連する問題