简体   繁体   English

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

[英]Variadic templated constructor does not take x arguments

For an inner templated struct of a templated class, I want to have a variadic templated constructor. 对于模板化类的内部模板化结构,我想要一个可变参数的模板化构造函数。 Unfortunately the constructor (see first constructor below) does not suffice: if I only use that constructor, I obtain C2260 compiler errors stating that the constructor function does not take 3, 4 or 5 arguments. 不幸的是,构造函数(请参见下面的第一个构造函数)不能满足要求:如果仅使用该构造函数,则会出现C2260编译器错误,指出构造函数没有3、4或5个参数。 On the other hand, making everything explicit by adding another three constructors (see remaining constructors below) works as intended. 另一方面,通过添加另外三个构造函数(请参阅下面的其余构造函数)使所有内容显式工作即可。

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

           ...
    }
}

The constructor is called like this: 构造函数的调用方式如下:

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

For a primitive like a bool as variadic argument, everything works fine. 对于像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

Where line 37 corresponds to the constructor call ( new ResourcePoolEntry< DerivedResourceT >(*this, key, args...)); 其中第37行对应于构造函数调用( new ResourcePoolEntry< DerivedResourceT >(*this, key, args...)); in the example above) 在上面的示例中)

What am I doing wrong? 我究竟做错了什么? (Compiler MSVC++ 14.0) (编译器MSVC ++ 14.0)

Minimal Example: 最小示例:

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

Error : 错误

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

One thing to note (which may or may not be the ultimate cause of your problem) is that you're not doing quite the right thing with your template parameter forwarding. 需要注意的一件事(可能是导致问题的最终原因,也可能不是导致问题的最终原因)是,您在模板参数转发方面做的不够正确。 For example, in the case where you're passing an ID3D11Device2 your DerivedResourceT constructor probably (judging by the signature of your non-variadic constructors) expects a reference - however because of the way template deduction works it will actually get a copy instead (if indeed this is even permissable - if not it would not compile). 例如,在传递ID3D11Device2的情况下,您的DerivedResourceT构造函数(通过非可变构造函数的签名判断)可能需要引用-但是由于模板推导的工作方式,它实际上将获得一个副本(如果实际上,这甚至是允许的-否则将无法编译)。

To correct this, you need to use the standard forwarding recipe, which allows the correct l- or r-valueness of a passed parameter to be passed on, which includes correctly forwarding references: 要更正此问题,您需要使用标准转发配方,该转发配方允许传递所传递参数的正确的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) {}

In the above, note the && in the parameter type of args... and the std::forward call. 在上面的代码中,请注意参数类型args...&&std::forward调用。

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

相关问题 在构造函数的可变参数中使用其他模板化类来执行模板化类的初始化 - Performing initialization of templated class using other templated classes in variadic arguments of constructor 构造函数:函数不接受 3 个参数 - Constructor: function does not take 3 arguments 使用可变参数 arguments 的构造函数重载 - Constructor overloading with variadic arguments std 线程构造函数是否采用可变参数线程 function? - Does std thread constructor take variadic thread function? 具有相同类型的可变参数模板参数的构造函数无法编译 - constructor with variadic template arguments of the same type does not compile 为什么我的可变参数模板构造函数不匹配其参数? - Why my variadic template constructor does not match its arguments? 使用可变参数模板化参数的构造函数和函数 - Constructor and functions using variadic templated parameters 可变参数模板类-0长度的包构造函数冲突 - Variadic templated class - 0 length package constructor collision C++ 前向可变参数模板化 arguments 到元组 - C++ Forward variadic templated arguments to tuple 将可变参数模板与模板化的类参数一起使用 - Using variadic templates with templated class arguments
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM