6

うーん、VC2012の奇妙なものです。テンプレート引数が非constポインターであるテンプレート化されたクラスの関数に、const参照によってconstポインターを渡すための構文を解決できないようです。

template<typename T>
struct Foo
{
    void Add( const T& Bar ) { printf(Bar); }
};

void main()
{
Foo<char*> foo;
const char* name = "FooBar"; 
foo.Add(name);                 // Causes error
}

したがって、ここで問題を単純化しましたが、基本的には「追加」への引数に const T ie const char* を持たせたいと考えています。私はもう試した:

void Add( const (const T)& Bar ); 

typedef const T ConstT;
void Add( const (ConstT)& Bar );  

void Add( const typename std::add_const<T>::type& Bar ); 

どれも機能しません。私が得ている正確なエラーは次のとおりです。

error C2664: 'Foo<T>::Add' : cannot convert parameter 1 from 'const char *' to 'char *const &'
          with
          [
              T=char *
          ]
          Conversion loses qualifiers 

私が見ることができるのは正しいですが、constキャスト 'name'を非constにせずに解決するにはどうすればよいですか。

4

5 に答える 5

3

ポインター型をテンプレート型にマップするとすぐに、ポインター自体にのみ const-ness をポイント先の型に追加できなくなるため、ここでの問題のようです。あなたがやろうとしているように見えるのは、関数のパラメーターに constness を自動的に追加することです (したがって、T が関数である場合は、記述したのではなくchar*受け入れる必要があります)。これを行う唯一の方法は、別のテンプレートを使用して、次のようにポインター型の指す先に constness を追加することです。欠落しているヘッダーを含め、署名を修正する自由を取りました:const char* const&char* const&main

#include <cstdio>

template<typename T>
struct add_const_to_pointee
{
    typedef T type;
};

template <typename T>
struct add_const_to_pointee<T*>
{
    typedef const T* type;
};

template<typename T>
struct Foo
{
    void Add( typename add_const_to_pointee<T>::type const & Bar ) { printf(Bar); }
};

int main()
{
    Foo<char*> foo;
    const char* name = "FooBar";
    foo.Add(name);                 // Causes error
}

ただし、別の別の記事で述べたようstd::stringに、C スタイルの文字列の代わりに使用すると、この問題はなくなります。

于 2013-04-22T16:40:30.463 に答える
1

toconst char*の代わりに渡すことができない場合は、 を使用して正しい型を微調整できます。これにより、ポインター修飾子が削除され、より明示的な型を提供できるようになります。char*Foostd::remove_pointer

#include <type_traits>

template<typename T>
struct Foo
{
    void Add(typename std::remove_pointer<T>::type const*& Bar ) { printf(Bar); }
};

ポインター値が変更されないようにするために、参照も宣言できますconst

void Add(typename std::remove_pointer<T>::type const* const& Bar )
{ Bar = "name"; } // <- fails

型をポインターからポインターに減らす必要がある場合は、std::decay一緒に使用できますstd::remove_pointer

void Add(typename std::remove_pointer<typename std::decay<T>::type>::type const*& Bar)
{
    printf(Bar);
}

これは、要件が何であるかによって異なりますTchar基本型 (例: ) のみが渡されると想定し、Tそこから参照型とポインター型を構築することをお勧めします。

于 2013-04-22T16:03:34.743 に答える
1

Foo オブジェクトへのテンプレート引数を に変更する必要がありますFoo<const char*>。ならT=char*、そうでconst T=char*constはないからconst char*です。強制的に動作させようとするのは得策ではなく、未定義の動作が発生する可能性があります。

于 2013-04-22T15:29:33.960 に答える