13

考虑代码:是否合法,以部分地专门与来自外部类的可变参数模板ARGS可变参数模板内部类

#include <iostream> 

template <class... Ts> 
struct outer { 
    template <class... ITs> 
    struct inner { 
     static constexpr bool value = false; 
    }; 

    template <class... ITs> 
    struct inner<Ts..., ITs...> { 
     static constexpr bool value = true; 
    }; 
}; 

int main() { 
    std::cout << outer<int, float, double>::inner<int, float, double, int>::value << std::endl; 
} 

代码编译与铛++但不与克++,它产生一个错误:

temp3.cc:11:11: error: parameter pack argument ‘Ts ...’ must be at the end of the template argument list

struct inner<Ts..., ITs...> { 
    ^

由于我已经建立here内部类的部分专业化应该是合法的。

编辑: 出于完整性很值得补充说,铛上面的代码警告说,他可能会与推断它的参数还没有这样做没有任何问题一个问题...

+0

我完全不知道规则,但是当我得到一个依赖类型的错误时,在它有时帮助之前添加'typename'或'template'。试试'struct inner Dani

+0

添加'typename'后我得到'temp3.cc:11:39:错误:模板参数1无效' –

+0

请注意,请求的场景仍然可以通过一些额外的模板元编程实现... http:///coliru.stacked-crooked.com/a/0c6c643c8ff5809e(是的,我知道这不是问题,但实施它的挑战是不可避免的...)。 –

回答

8

这是一个错误的gcc 。这是一个完全有效的偏特:

template <class... ITs> 
struct inner<Ts..., ITs...> { 
    static constexpr bool value = true; 
}; 

被推导的模板参数包必须要在后,ITs...满足这一点。但Ts...不是需要在这里推断的包,它只是一个特定的参数包。

此外,GCC编译几个等效制剂:

template <class... Ts> 
struct X { 
    template <class... Us> 
    static void foo(Ts..., Us...) { } 
}; 

int main() { 
    X<int>::foo(1, 'c'); 
} 

和:

template <class... Us> 
struct A { }; 

template <class... Ts> 
struct X { 
    template <class... Us> 
    static void foo(A<Ts..., Us...>) { } 
}; 

int main() { 
    X<int>::foo(A<int, char>{}); 
} 

这些等效结构良好的到原始示例。启发于巴里的回答

+0

我怀疑,但不知道模板类内是否存在专门化背景下的一些特殊规则。这是一个已知的错误吗? –

+4

我确实认为部分专业化是有意义的,但我不确定书面标准是否允许。 [14.5.5p8.5]说*如果一个参数是一个包扩展(14.5.3),它应该是模板参数列表*中的最后一个参数。这是对部分专业化的特定要求,因此它不适用于您的示例。这看起来更像是一个标准问题,而不是一个编译器bug。 – bogdan

+0

你应该将bug报告提交给'gcc'。你完成了吗? – Destructor

0

可能简单而有效的解决方法:

#include <iostream> 

template <class... Ts> 
struct pack { }; 

template <class... Ts> 
struct outer { 
    template <class IT> 
    struct inner { 
     static constexpr bool value = false; 
    }; 

    template <class... ITs> 
    struct inner<pack<Ts..., ITs...>> { 
     static constexpr bool value = true; 
    }; 
}; 

int main() { 
    std::cout << outer<int, float, double>::inner<pack<int, float, double, int>>::value << std::endl; 
} 

(它仍然在铛产生警告,虽然)

1

乘着WF的回答,仍然保持相同的主要作为原题:

#include <iostream> 

template <class... Ts> 
struct pack { }; 

template <class... Ts> 
class outer { 
    template <class IT> 
    struct _inner { 
     static constexpr bool value = false; 
    }; 

    template <class... ITs> 
    struct _inner<pack<Ts..., ITs...>> { 
     static constexpr bool value = true; 
    }; 
public: 
    template <class... ITs> 
    struct inner { 
     static constexpr bool value = _inner<pack<ITs...>>::value; 
    };  
}; 

int main() { 
    std::cout << outer<int, float, double>::inner<int, float, double, int>::value 
      << std::endl; 
} 

它仍然会产生在铛一个警告,因为_inner的专用版本无法地推出其...从TS列表中除了... ,IT ......(在struct _inner<pack<Ts..., ITs...>>) - 但是代码并不要求IT从Ts ...,ITs列表中单独推导出来,所以这应该没问题。

在g ++中,它编译时没有警告。

代码:http://coliru.stacked-crooked.com/a/ae3b21dd847450b2

(对于没有警告也在铛溶液:http://coliru.stacked-crooked.com/a/0c6c643c8ff5809e)。

相关问题