2017-01-19 8 views
5

私は本を読む< C++のテンプレート - 完全なガイド>とポインタのためのテンプレートの特化を学んだ。 (多分私は本のこの部分を誤解)ポインタのC++テンプレートの特殊化?

(1)ここに私の単純なテンプレートです:

$ g++ main.cpp -o main.exe 
main.cpp:10:29: error: non-type partial specialization ‘Function<T*>’ is not allowed 
void Function<T*>(const T* a) 

:G ++ 5.3、コンパイラのレポート私はubuntu16.04のx64を使用

#include <iostream> 

template<typename T> 
void Function(const T& a) 
{ 
    std::cout << "Function<T>: " << a << std::endl; 
} 

template<typename T> 
void Function<T*>(const T* a) 
{ 
    std::cout << "Function<T*>: " << a << std::endl; 
} 

int main(void) 
{ 
    Function(1); 
    Function(1.2); 
    Function("hello"); 
    Function((void*)0x25); 

    return 0; 
} 

、 (2)しかし、このコードは正しい:

#include <iostream> 

template<typename T> 
void Function(const T& a) 
{ 
    std::cout << "Function<T>: " << a << std::endl; 
} 

int main(void) 
{ 
    Function(1); 
    Function(1.2); 
    Function("hello"); 
    Function((void*)0x25); 

    return 0; 
} 

結果を示す:

$ g++ main.cpp -o main.exe 
$ ./main.exe 
Function<T>: 1 
Function<T>: 1.2 
Function<T>: hello 
Function<T>: 0x25 

私の質問です:ポインタ専門に関する本は間違っていますか?または、私は本のこの部分の意味を誤解していますか?または、他の何か ?

クラス内のポインターの特殊化についての更新。

ポインタ専門と

(3)テンプレートクラス:

$ g++ main.cpp -o main.exe 
main.cpp: In function ‘int main()’: 
main.cpp:37:27: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] 
    Base<char*> b3("hello"); 
         ^
$ ./main.exe 
12 
2.4 
hello 
0x25 
ポインタ特化せず

(4)テンプレートクラス:

#include <iostream> 

template<typename T> 
struct Base { 
    T member; 

    Base(const T& a) 
     : member(a) 
    { 
    } 

    void hello() 
    { 
     std::cout << member << std::endl; 
    } 
}; 

int main(void) 
{ 
    Base<int> b1(12); 
    Base<double> b2(2.4); 
    Base<char*> b3("hello"); 
    Base<void*> b4((void*)0x25); 

    b1.hello(); 
    b2.hello(); 
    b3.hello(); 
    b4.hello(); 

    return 0; 
} 

#include <iostream> 

template<typename T> 
struct Base { 
    T member; 

    Base(const T& a) 
     : member(a) 
    { 
    } 

    void hello() 
    { 
     std::cout << member << std::endl; 
    } 
}; 

template<typename T> 
struct Base<T*> { 
    T* member; 

    Base(T* a) 
     : member(a) 
    { 
    } 

    void hello() 
    { 
     std::cout << member << std::endl; 
    } 
}; 

int main(void) 
{ 
    Base<int> b1(12); 
    Base<double> b2(2.4); 
    Base<char*> b3("hello"); 
    Base<void*> b4((void*)0x25); 

    b1.hello(); 
    b2.hello(); 
    b3.hello(); 
    b4.hello(); 

    return 0; 
} 

このコードは1つの警告と正しいです

の結果は同じです:

$ g++ main.cpp -o main.exe 
main.cpp: In function ‘int main()’: 
main.cpp:39:27: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] 
    Base<char*> b3("hello"); 
         ^
$ ./main.exe 
12 
2.4 
hello 
0x25 

これは、ポインタの特殊化が不要であることを意味しますか? または、この機能は別のコンパイラで異なる動作をするかもしれませんか?

+0

のを待ちますか?それはどこにも使われていないのですか?同じ関数が2回宣言されているのはなぜですか?コンパイラエラーとは何ですか?関連コードを投稿してください。 – stijn

+1

通常、その答えはエラーメッセージです。あなたはそれを見ましたか? – user2079303

+1

私がclangで受けるエラーは 'error:function template partial specialization is not allowed'です。 GCCは同様の報告をしている。それはあなたの質問に答えるはずです。 – DeiDei

答えて

3

エラーメッセージが間違っている何を言った:

non-type partial specialization ‘Function<T*>’ is not allowed 

あなたは部分的にしか型(クラス)を特化することができます。関数を部分的に特殊化しようとしました。関数は型ではありません。あなたはそれらを完全に専門化することができます。

+0

ああ、私の間違い。 – linrongbin

1

2つの問題:あなたは、部分的に機能を特化することはできません

  1. (void*)0x25の振る舞いは、であり、定義されていません。です。 nullptrを除いて、配列の最後の要素を超えたものとスカラーのアドレスを過ぎたものの1つを除き、あなたが所有していないメモリへのポインタを設定することはできません。

+0

(void *)0x25は本の中ではありませんが、私の間違いです。 – linrongbin

4

すでに述べたように、機能テンプレートの部分的な特殊化は許可されていません。あなたはこのためstd::enable_ifを使用することができます。

template <typename T, typename std::enable_if_t<!std::is_pointer<T>::value>* = 0> 
void func(T val) { std::cout << val << std::endl; } 

template <typename T, typename std::enable_if_t<std::is_pointer<T>::value>* = 0> 
void func(T val) { func(*val); } 

あなたは簡単な構文を探している場合は、テストでどのような概念

関連する問題