2017-03-22 9 views
1

テンプレートクラスの内側のテンプレート構造体については、バリデーションテンプレートコンストラクタが必要です。残念ながら、コンストラクター(以下の最初のコンストラクターを参照)で十分ではありません。そのコンストラクターのみを使用すると、コンストラクター関数が3つ、4つまたは5つの引数を取らないことを示すC2260コンパイラー・エラーが発生します。一方、別の3つのコンストラクタを追加することで明示的にすべてを明示的にする(以下のコンストラクタの残りを参照してください)。コンストラクタは、このように呼ばれてVariadicのテンプレートコンストラクタはx引数を受け取りません

template< typename KeyT, typename ResourceT > 
class ResourcePool { 

    ... 

    template< typename DerivedResourceT > 
    struct ResourcePoolEntry final : public DerivedResourceT { 

     template< typename... ConstructorArgsT > 
     ResourcePoolEntry(ResourcePool< KeyT, ResourceT > &resource_pool, 
      KeyT resource_key, ConstructorArgsT... args) 
      : DerivedResourceT(args...), m_resource_pool(resource_pool), m_resource_key(resource_key) {} 

     ResourcePoolEntry(ResourcePool< KeyT, ResourceT > &resource_pool, 
      KeyT resource_key, ID3D11Device2 &x) 
      : DerivedResourceT(x), m_resource_pool(resource_pool), m_resource_key(resource_key) {} 

     ResourcePoolEntry(ResourcePool< KeyT, ResourceT > &resource_pool, 
      KeyT resource_key, ID3D11Device2 &x, const wstring &y) 
      : DerivedResourceT(x,y), m_resource_pool(resource_pool), m_resource_key(resource_key) {} 

     template < typename VertexT > 
     ResourcePoolEntry(ResourcePool< KeyT, ResourceT > &resource_pool, 
      KeyT resource_key, ID3D11Device2 &x, const wstring &y, const MeshDescriptor<VertexT> &z) 
      : DerivedResourceT(x, y, z), m_resource_pool(resource_pool), m_resource_key(resource_key) {} 

      ... 
    } 
} 

boolとして可変長引数のようなプリミティブについて

template< typename KeyT, typename ResourceT > 
template< typename... ConstructorArgsT > 
std::shared_ptr<ResourceT> ResourcePool< KeyT, ResourceT >::GetResource(KeyT key, ConstructorArgsT... args) { 
    return GetDerivedResource< ResourceT, ConstructorArgsT... >(key, args...); 
} 

template< typename KeyT, typename ResourceT > 
template< typename DerivedResourceT, typename... ConstructorArgsT > 
std::shared_ptr<ResourceT> ResourcePool< KeyT, ResourceT >::GetDerivedResource(KeyT key, ConstructorArgsT... args) { 
    ... 
    auto new_resource = std::shared_ptr< ResourcePoolEntry<DerivedResourceT> >(
     new ResourcePoolEntry<DerivedResourceT>(*this, key, args...)); 
    ... 
} 

、すべてが正常に動作します。ライン37は、私が間違っているのは何

(上記の例ではnew ResourcePoolEntry<DerivedResourceT>(*this, key, args...));)コンストラクタ呼び出しに対応

Severity Code Description Project File Line Suppression State 
Error C2660  'mage::ResourcePool<std::wstring,mage::VertexShader>::ResourcePoolEntry<DerivedResourceT>::ResourcePoolEntry': function does not take 3 arguments MAGE c:\users\matthias\documents\visual studio 2015\projects\mage\mage\mage\src\resource\resource_pool.tpp 37 

? (コンパイラMSVC++ 14.0)

最小例:

#include <memory> 
#include <map> 

template < typename T > 
using SharedPtr = std::shared_ptr<T>; 

template < typename T > 
using WeakPtr = std::weak_ptr<T>; 

template< typename KeyT, typename ResourceT > 
using ResourceMap = std::map< KeyT, WeakPtr<ResourceT> >; 

template< typename KeyT, typename ResourceT > 
class ResourcePool { 

public: 

    template< typename... ConstructorArgsT > 
    SharedPtr<ResourceT> GetResource(KeyT key, ConstructorArgsT... args); 
    template< typename DerivedResourceT, typename... ConstructorArgsT > 
    SharedPtr<ResourceT> GetDerivedResource(KeyT key, ConstructorArgsT... args); 

private: 

    ResourceMap< KeyT, ResourceT > m_resource_map; 

    template< typename DerivedResourceT > 
    struct ResourcePoolEntry final : public DerivedResourceT { 

    public: 

     template< typename... ConstructorArgsT > 
     ResourcePoolEntry(ResourcePool< KeyT, ResourceT > &resource_pool, 
      KeyT resource_key, ConstructorArgsT... args) 
      : DerivedResourceT(args...), m_resource_pool(resource_pool), m_resource_key(resource_key) {} 
    private: 

     ResourcePool< KeyT, ResourceT > &m_resource_pool; 
     KeyT m_resource_key; 
    }; 
}; 

template< typename KeyT, typename ResourceT > 
template< typename... ConstructorArgsT > 
SharedPtr<ResourceT> ResourcePool< KeyT, ResourceT >::GetResource(KeyT key, ConstructorArgsT... args) { 
    return GetDerivedResource< ResourceT, ConstructorArgsT... >(key, args...); 
} 

template< typename KeyT, typename ResourceT > 
template< typename DerivedResourceT, typename... ConstructorArgsT > 
SharedPtr<ResourceT> ResourcePool< KeyT, ResourceT >::GetDerivedResource(KeyT key, ConstructorArgsT... args) { 
    auto it = m_resource_map.find(key); 
    if (it != m_resource_map.end()) { 
     auto resource = it->second.lock(); 
     if (resource) { 
      return resource; 
     } 
     else { 
      m_resource_map.erase(it); 
     } 
    } 

    auto new_resource = SharedPtr< ResourcePoolEntry<DerivedResourceT> >(
     new ResourcePoolEntry<DerivedResourceT>(*this, key, args...)); 
    m_resource_map[key] = new_resource; 
    return new_resource; 
} 

#include <d3d11_2.h> 

struct A { 
}; 
struct B : public A { 
    B(ID3D11Device &device) : A() {} 
}; 


const D3D_FEATURE_LEVEL g_feature_levels[] = { 
    D3D_FEATURE_LEVEL_11_1, 
    D3D_FEATURE_LEVEL_11_0 
}; 

int main() { 

    ID3D11Device *device; 
    ID3D11DeviceContext *device_context; 
    D3D_FEATURE_LEVEL feature_level; 
    D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, 
     g_feature_levels, _countof(g_feature_levels), D3D11_SDK_VERSION, 
     &device, &feature_level, &device_context 
    ); 

    ResourcePool< char, A > *pool = new ResourcePool< char, A >(); 
    //pool->template GetResource< int & >('a'); 
    pool->template GetDerivedResource< B, ID3D11Device & >('b', *device); 
} 

エラー:注意すべき

Severity Code Description Line Suppression State 
Error C2661 'ResourcePool<char,A>::ResourcePoolEntry<DerivedResourceT>::ResourcePoolEntry': no overloaded function takes 3 arguments 66 
+1

実際のエラーテキストを提供しています。実際の行について。理想的には、エラーを生成する[MCVE]を提供してください。これは、無関係なものを削除するためにコードを変更する必要があるかもしれません。あなたが「細部を取り除く」に重要なものを取り除いたかどうかを知ることは非常に難しく、あなたの心を読むのは苦痛になります。私はあなたのバリデーションされたctorが値*で物事を取るのに対し、あなたのマニュアルは参照とconst参照が混在しています。 – Yakk

+0

@ Yakk私のバリデーションは、私がそれを渡す方法ですべてを取っていませんか? – Matthias

+1

物事は価値があります。これは問題を引き起こす可能性があります。実際にビルドエラーが発生していないため、作業しているすべてのタイプがわからないため、わかりません。再度[MCVE]と実際のエラー、またはあなたの質問は悪いものです。 – Yakk

答えて

2

ことの一つは、(よく、または問題の究極的な原因ではないかもしれない)ということですあなたはあなたのテンプレートパラメータの転送でかなり正しいことをしていません。たとえば、ID3D11Device2DerivedResourceTコンストラクタをおそらく(非可変コンストラクタのシグネチャで判断して)参照すると考えられますが、テンプレート控除が機能するため、実際にはコピーを取得します(if確かにこれは許されています - そうでなければそれはコンパイルされません)。

template< typename... ConstructorArgsT > 
ResourcePoolEntry(ResourcePool< KeyT, ResourceT > &resource_pool, 
      KeyT resource_key, ConstructorArgsT&&... args) 
      : DerivedResourceT(std::forward<ConstructorArgsT>(args)...), m_resource_pool(resource_pool), m_resource_key(resource_key) {} 

で:

はこれを修正するには、正しく転送の参照が含まれ、渡されたパラメータの正しい1-またはr-valuenessがオンに渡すことができ、標準の転送レシピを、使用する必要があります上記のように、 args...std::forwardというパラメータタイプの &&に注意してください。

+0

これは解決策のようですが、中国語のようです。 reference-to-reference &&を前に使用したことはありません。また、中間呼び出しGetResource - > GetDerivedResource &&は使用しないでください。 – Matthias

+1

はい、あなたは、完全な転送レシピは、l値またはr値となる可能性のあるテンプレートパラメータを転送するときに常に使用する必要があります。 [Here](http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html)は、r値の参照をいくらか説明するリンクです'&&'構文)と[here](http://eli.thegreenplace.net/2014/perfect-forwarding-and-universal-references-in-c/)は完全な転送を説明するものです – Smeeheey

+0

参考に感謝します。それは理にかなっています(プリミティブ型はフルチェーンに沿って参照によって渡されます)。 – Matthias

関連する問題