偏特

2015-08-14 61 views
2

过程中使用非类型模板参数考虑以下struct S:偏特

//Implementations provided elsewhere 

struct A { A(int i, double d, std::string s); /* ... */ }; 
struct B { B(double d1, double d2);   /* ... */ }; 

我有两个转换类,它们的模板签名的样子:

TupleAs< A, int, double, std::string > via1 { ... }; 
ArrayAs< B, double, 2 >    via2 { ... }; 

可以预见的是,TupleAs转换的三重int,doublestd::string值转换成A类型的对象。同样,ArrayAs将一对两个double值转换为B类型的对象。 (是的,是有原因的,我不能直接调用AB构造函数)。

提高语法

我想改变语法,所以我可以做到以下几点:

TupleAs< A(int,double,std::string) > via1 { ... }; 
ArrayAs< B(double,2) >    via2 { ... }; 

我认为这更多地描述了转换过程。该TupleAs模板声明和相应的局部专业化应该是这样的:

template <typename T> struct TupleAs; 

template <typename T, typename ... Args> 
struct TupleAs<T(Args...)> { ... }; 

编译器错误

但是,如果我尝试做与ArrayAs版本类似的东西:

template <typename T> struct ArrayAs; 

template <typename T, typename U, unsigned N> 
struct ArrayAs<T(U,N)> { ... }; 

我尝试实例化时在叮当(3.6)中出现以下错误(ArrayAs< B(double,2)> test;):

typeAs.cpp:14:22: error: unknown type name 'N' 
    struct ArrayAs<T(U,N)>{ 
        ^
typeAs.cpp:14:10: warning: class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used 
    struct ArrayAs<T(U,N)>{ 
     ^~~~~~~~~~~~~~~ 
typeAs.cpp:13:45: note: non-deducible template parameter 'N' 
    template<typename T, typename U, unsigned N> 
              ^

gcc错误诊断有点不同,但我不会在这里发表。我承认我的模板技能应该比他们更好,我也承认类似的std::function<B(double,2)>声明显然是无稽之谈。但有人可以告诉我为什么我不想让特定的语法实现吗?我查看了C++ 14标准,并且无法找到相关部分,而且我在解释叮当声诊断消息时遇到了问题。

+3

您正在专注于功能类型。函数类型的形式为'type(types ...)',没有空间存放整数。换句话说,在任何情况下,B(double,2)语法在C++中都没有意义。错误消息可以承认更有意义。 – Quentin

+0

你需要'2'作为编译时参数吗? – sfjac

回答

2

当你专注TupleAs

template <typename T, typename ... Args> 
struct TupleAs<T(Args...)> 

你基本上是重载一个函数的符号。您正在专注于函数,它需要Args...并返回T。这是一种类型。你可能不会将该函数用作函数,或者真的把它看作是一个类型,但事实就是如此。

在另一方面,在这里:

​​

有作为需要N功能没有这样的事情。它可能需要unsigned,但它不能采取。没有这种合理的东西。从你的例子来看,B(double, 2)根本没有意义。在最好的情况,你可以写东西,使:

template <unsigned N> using size_ = std::integral_constant<size_t, N>; 

ArrayAs< B(double,size_<2>) > 

甚至:

ArrayAs< B(std::array<double, 2>) > 

,因为现在我们又回到使用类型无处不在。无论你喜欢或不喜欢,都是个人喜好。

这里的关键是,类型是所有事物模板元编程的头等公民,在可能的情况下应避免使用值。

+0

不幸的是,'ArrayAs '不起作用。 – Yakk

+0

@Yakk'ArrayAs ''确实,但* yuck *。怪数列衰变:p – Quentin

+1

@Yakk我流下了眼泪 – Barry

2
template <typename T> struct ArrayAs; 

template <typename T, typename U, std::size_t N> 
struct ArrayAs<T(std::array<U,N>)> { ... }; 

作品,会:

template<class T> 
struct to_array; 
template<class T, size_t N> 
struct to_array<T[N]> { using type = std::array<T, N>; }; 
template<class T> 
using arr = typename to_array<T>::type; 

则:

ArrayAs< Bob(arr<int[3]>) > some_var; 

live example

不幸的是,直接使用ArrayAs< Bob(int[3]) >不起作用,因为函数类型中的数组如何衰减指针。

+0

我没有想过尝试使用数组下标的语法,谢谢。 – KyleKnoepfel