2010-07-15 64 views
3

不完全确定如何标注此问题或搜索什么,如果这与另一个问题相同,请关闭并重定向到相应的问题。整数模板参数指定参数个数的类方法

假设

template<typename Type, int Size> class vector 
{ 
    Type data[Size]; 
} 

是否有可能更换一个构造函数,采用的参数大小数模板特喜欢这个

template<typename Type> class vector3<Type,3> 
{ 
    Type data[3]; 
    public: 
    vector3(Type, Type, Type); 
} 

的东西在非专业模板类?像一个“可变参数构造函数”,它产生一个构造函数,其大小数量为Type类型的参数。

涉及C++ 0x功能的解决方案很好。

回答

5

在C++ 0x你有template typedef终于可用!

免责声明:什么也没有编...

维基百科的文章:

template< typename second> 
using TypedefName = SomeType<OtherType, second, 5>; 

而你的情况会产生

template <class Type> 
using vector3 = vector<Type, 3>; 

我不能告诉你如何很多我渴望这个;)

但它不能解决参数问题。如前所述,你可以尝试在这里使用可变参数模板,但是我不确定在这种情况下它们的应用。正常的使用是递归方法,你需要在中间放一个static_assert

编辑考虑到意见。

template <class Type, size_t Size> 
class vector 
{ 
public: 
    template <class... Args> 
    vector(Args... args): data({args...}) 
    { 
    // Necessary only if you wish to ensure that the exact number of args 
    // is passed, otherwise there could be less than requested 
    BOOST_MPL_ASSERT_RELATION(sizeof...(Args), ==, Size); 
    } 

private: 
    T data[Size]; 
}; 

已有的另一种可能性是将预处理器生成与boost::enable_if相结合。

template <class Type, size_t Size> 
class vector 
{ 
public: 
    vector(Type a0, typename boost::enable_if_c< Size == 1 >::type* = 0); 
    vector(Type a0, Type a1, typename boost::enable_if_c< Size == 2 >::type* = 0); 
    // ... 
}; 

使用Boost.Preprocessor进行生成使得这更容易。

BOOST_PP_REPEAT(MAX_COUNT, CONSTRUCTOR_MACRO, ~); 

// where MAX_COUNT is defined to the maximum size you wish 
// and CONSTRUCTOR_MACRO actually generates the constructor 

#define CONSTRUCTOR_MACRO(z, n, data)        \ 
    vector(               \ 
    BOOST_PP_ENUM_PARAMS(n, Type a),        \ 
    typename boost::enable_if_c< Size == n >::type* = 0   \ 
); 

构造函数的实现留给读者练习。这是另一个电话BOOST_PP_REPEAT。正如你所看到的,它很快变得丑陋,所以如果你可以使用可变模板版本,你会变得更好。

+0

sizeof ...(Args)的模板参数个数? – Tomek 2010-07-15 17:25:11

+0

也许,我从来没有需要它,我找不到任何参考... – 2010-07-15 17:35:33

+1

通过使用初始化程序列表:'data({args ...})'摆脱您的'init'函数 – phlipsy 2010-07-15 20:06:22

2

是否有可能取代一个构造函数,采用的参数大小数模板特喜欢这个

不是没有一吨的重复,机械的代码,并且最大尺寸将由数量限制你重复自己的时间。例如:boost::tuple(它可能正是你想要的功能)。

在C++ 0x这将不会是一个问题多亏了variadic templates

3

有进一步的解决问题的方法:在初始化列表中

template<typename T, unsigned int N> 
struct vector { 
    T data[N]; 

    template<typename... Args> 
    vector(Args... args) : data({args...}) { } 
}; 

但是参数的个数仅需要小于或等于比N使用可变参数模板参数和它们的类型只需要可以转换成T

+0

适用于我也是我想我的措辞听起来像“确切”是一个要求。我会编辑说至少。在这种情况下,构造函数应该默认构造其他成员(如果有的话),对吗? – bpw1621 2010-07-16 00:40:03

+0

@ bpw1621:对。但是正如卡斯平告诉你应该考虑使用'array'也提供一个固定长度的数组。但是,如果您需要为您的类型重载算术运算,则您将被迫在内部'array'中理想地编写自己的新类。 – phlipsy 2010-07-16 13:20:31

+0

哈哈,我在看到这个答案之前写了很多代码来做到这一点。 :P – CodeRarity 2013-02-14 02:55:04

2

首先您应该考虑使用std::array。它不符合你的所有要求,但它足够接近,如果差异无关紧要,你可以节省很多工作。问题是这样的廉价版本将具有构造接受2个参数,以及3

template< typename T> 
using Vector3 = std::array<T,3>; 

Vector3 v1{1,2,3}; 
Vector3 v2{1,2}; // it sounds like you want to disallow this case. 

否则,你可以创建一个充当很像std::array,除了用更挑剔的构造函数的自定义类。

template<typename T, std::size_t SIZE> 
class Vector 
{ 
public: 
    template< typename ... Args > 
    Vector(Args ... args) : 
     data({args...}) 
    { 
     static_assert(sizeof...(Args) == SIZE, 
        "Incorrect number of arguments passed to Vector constructor"); 
    } 
    /* lots of extra code here to add std::array -like methods */ 
private: 
    // could use std::array here as well. 
    T data[3]; 
}; 

template< typename T > 
using Vector3 = Vector<T,3>; 

Vector3 v1(1,2,3); 
Vector3 v2(1,2); // error at compile time. 
+0

好主意,使用static_assert来保证参数的确切数量。有关它们类型的任何想法?他们只能转换为'T' ... – phlipsy 2010-07-16 13:15:33

+0

我可以使用'std :: same_type '添加另一个'static_assert'来强制执行正确的类型,但我认为这会自我挫败。我想'Vector3 vi(11,12,13)'只是工作。如果我需要确切类型,我必须将无符号说明符添加到整数文字。 – 2010-07-16 13:53:31

相关问题