模板模板部分专业化只使用-std = c ++ 1z与g ++ [英] Template template partial specialization only working with -std=c++1z with g++

查看:1444
本文介绍了模板模板部分专业化只使用-std = c ++ 1z与g ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现以下代码片段:

  #include > 
#include< vector>

模板< typename T>
struct X:std :: false_type {};

模板< template< typename> Y类,typename U>
struct X< Y< U>> :std :: true_type {};

int main(){
if(X ())
std :: cout<< wrong\\\
; $(< std :: vector< double>>())
std :: cout<< correct\\\
;

返回0;
}

只能打印正确当用 g ++ - 7 -std = c ++ 1z 编译时。其他版本的 g ++ clang ++ 或其他 std 标志失败这是一个当前实现的bug,这段代码不应该打印任何内容,或者是在C ++ 17中改变了这个代码如我所料?

解决方案

这是采用 P0522 in C ++ 17,其动机来自于这个例子:


 模板< template< int>类> void FI(); 
模板< template< auto>类> void FA();
模板< auto> struct SA {/ * ... * /};
模板< int> struct SI {/ * ... * /};
FI< SA>(); // 好;本文前的错误
FA< SI>(); //错误

模板< template< typename>类> void FD();
模板< typename,typename = int> struct SD {/ * ... * /};
FD< SD>(); // 好;本文前的错误(CWG 150)


以前, [temp.arg.template]所需的模板模板参数完全匹配。给出:

 模板< template< class>班级P> X类; 

模板< class T> A类;
模板< class T,class U = T> B类;
模板< class ...> C类;

X 显然是可以的,但 X 格式不正确,因为 B 需要两个模板参数(无论是否为默认值!)和由于 P 需要一个模板参数, C code>需要一个包(即使你可以用一个参数形成一个 C !)



如果模板模板参数至少与参数一样特殊,新的措辞会将匹配的想法放松到更有意义的模式。这使得 X< B> X< C> 都可以工作。



因此,在C ++ 17中, X 应该选择专业化。但在C ++ 17之前,它应该选择主要的。 gcc正在做正确的事情。

I have found that the following piece of code:

#include <iostream>
#include <vector>

template <typename T>
struct X : std::false_type {};

template <template <typename> class Y, typename U>
struct X<Y<U>> : std::true_type {};

int main() {
  if (X<int>())
    std::cout << "wrong\n";

  if (X<std::vector<double>>())
    std::cout << "correct\n";

  return 0;
}

Only prints correct when compiled with g++-7 with -std=c++1z. Other versions of g++, clang++ or other std flags fail to produce correct.

Is this a bug of the current implementation, and this code should not print anything, or is something changed in C++17 which makes this code work as I expect?

解决方案

This is a result of the adoption of P0522 in C++17, whose motivation was, from the example:

template <template <int> class> void FI();
template <template <auto> class> void FA();
template <auto> struct SA { /* ... */ };
template <int> struct SI { /* ... */ };
FI<SA>();  // OK; error before this paper
FA<SI>();  // error

template <template <typename> class> void FD();
template <typename, typename = int> struct SD { /* ... */ };
FD<SD>();  // OK; error before this paper (CWG 150)

Previously, the wording in [temp.arg.template] required template template parameters to match in kind exactly. So given:

template <template <class > class P> class X;

template <class T> class A;
template <class T, class U=T> class B;
template <class... > class C;

X<A> is clearly okay, but X<B> is ill-formed because B takes two template parameters (regardless if one is defaulted!) and X<C> is ill-formed because P expects one template parameter and C takes a pack (even if you could form a C with only a single parameter!)

The new wording loosens the idea of a match to one which makes more sense - if the template template-parameter is at least as specialized as the argument. That makes X<B> and X<C> both work.

Hence, in C++17, X<std::vector<double>> should pick the specialization. But before C++17, it should pick the primary. gcc is doing the right thing.

这篇关于模板模板部分专业化只使用-std = c ++ 1z与g ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆