繁体   English   中英

使用可变参数模板化参数的构造函数和函数

[英]Constructor and functions using variadic templated parameters

我想编写一个由多个维度作为模板的类:

namespace detail {
    enum class enabler {};
}

template<size_t dim>
class templateClass
{
public:
    template<class... DimArgs, typename std::enable_if<sizeof...(DimArgs)==dim, detail::enabler>::type...>
    templateClass(DimArgs... dimensions) {
    // Use integers passed to the constructor, one for each dimension
    }
};

在此几乎静态的if链接中可以找到detail::enabler枚举。 在这里,它用作第二个参数包,允许传递0个参数。 有作用域的枚举没有成员,并且不能(?)被意外传递。

他们还使用using声明来吞下某些typename等部分,但是我已经输入了完整的内容,以避免不得不在那里阅读它。

如何使用已通过的dimensions 参数包

该课程效果很好,例如:

templateClass<2> temp(5, 2);     // works
templateClass<3> temp(5, 2, 4);  // works
templateClass<1> temp(5,2);      // would give compile-time error

但是也许我对在这里应该使用/执行的操作有一个(或几个)坏主意?

编辑:我发现一种解决方案是创建一个std::initializer_list 我可以使用intsize_t类创建此文件,在这里效果很好。 但是,如果我不知道要传递的参数的类型(例如,由于我的函数出于某些其他目的可以同时使用intdouble ),那么还有比以下更好的方法:

std::initializer_list<int> list{dimensions...};
for (int i : list) {
    std::cout << "i = " << i << std::endl;
}

完整的工作示例:

网格高度:

#ifndef MESH_H
#define MESH_H

#include <type_traits>
#include <initializer_list>
#include <iostream>

namespace detail {
    enum class enabler {};
}

template <bool Condition>
using EnableIf =
    typename std::enable_if<Condition, detail::enabler>::type;

template<size_t meshDim>
class Mesh
{
public:
    template<class... DimArgs, EnableIf<sizeof...(DimArgs)==meshDim>...>
    Mesh(DimArgs... dimensions){
        std::initializer_list<int> list{dimensions...};
        for (int i : list) {
            std::cout << "i = " << i << std::endl;
        }
    }
};
#endif // MESH_H

main.cpp:

#include <iostream>
#include "Mesh.H"

int main()
{
    Mesh<2> mesh(5, 2);
    return 0;
}

使用g++ --std=c++11 main.cpp编译

可以通过将参数包放入元组来建立索引:

using T1 = std::tuple_element<0, std::tuple<DimArgs...>>; // Any index should work, not just 0

但是,这并不能完全解决可能的数字提升或缩小的问题。 我在想一些等于decltype(tuple_sum(dimensions...))的技巧(假设您可以假设它们是数字的)。 它可能看起来像这样(未经测试):

template<typename T>
constexpr T tuple_sum(T n) {return n;}

template<typename T, typename... Rest>
constexpr auto tuple_sum(T first, Rest... rest) {
    return first + tuple_sum(rest...);
}

为了使代码可移植,您不应具有匿名模板参数。

这是使用MinGW g ++ 5.1和Visual C ++ 2015编译的代码:

#include <utility>      // std::enable_if

#define IS_UNUSED( a ) (void) a; struct a

template< int dim >
class Tensor
{
public:
    template< class... Args
        , class Enabled_ = typename std::enable_if< sizeof...(Args) == dim, void >::type
        >
    Tensor( Args... args )
    {
        int const dimensions[] = { args... };
        IS_UNUSED( dimensions );
    }
};

auto main() -> int
{
    Tensor<2> tempA(5, 2);     // works
    Tensor<3> tempB(5, 2, 4);  // works
#ifdef FAIL
    Tensor<1> temp(5,2);      // would give compile-time error
#endif
}

暂无
暂无

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

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