繁体   English   中英

可变参数模板构造函数不接受x参数

[英]Variadic templated constructor does not take x arguments

对于模板化类的内部模板化结构,我想要一个可变参数的模板化构造函数。 不幸的是,构造函数(请参见下面的第一个构造函数)不能满足要求:如果仅使用该构造函数,则会出现C2260编译器错误,指出构造函数没有3、4或5个参数。 另一方面,通过添加另外三个构造函数(请参阅下面的其余构造函数)使所有内容显式工作即可。

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) {}

           ...
    }
}

构造函数的调用方式如下:

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...));
    ...
}

对于像bool这样的原始参数,一切都很好。

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

其中第37行对应于构造函数调用( new ResourcePoolEntry< DerivedResourceT >(*this, key, args...)); 在上面的示例中)

我究竟做错了什么? (编译器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

需要注意的一件事(可能是导致问题的最终原因,也可能不是导致问题的最终原因)是,您在模板参数转发方面做的不够正确。 例如,在传递ID3D11Device2的情况下,您的DerivedResourceT构造函数(通过非可变构造函数的签名判断)可能需要引用-但是由于模板推导的工作方式,它实际上将获得一个副本(如果实际上,这甚至是允许的-否则将无法编译)。

要更正此问题,您需要使用标准转发配方,该转发配方允许传递所传递参数的正确的l值或r值,其中包括正确的转发引用:

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) {}

在上面的代码中,请注意参数类型args...&&std::forward调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM