如何通过remove_cv函数推导出一个类型(const volatile int * vs const volatile int vs int * const volatile)

时间:2015-03-20 07:02:09

标签: c++ templates const

有一个功能" remove_cv" (http://en.cppreference.com/w/cpp/types/remove_cv)删除常量和易失性。

我的问题是为什么可以删除" const volatile int" to" int" 来自" int * const volatile" to" int *"但是" const volatile int *"与删除前相同。

The possible code is from the site
template< class T >
struct remove_cv {
    typedef typename std::remove_volatile<typename std::remove_const<T>::type>::type type;
};

template< class T > struct remove_const          { typedef T type; };
template< class T > struct remove_const<const T> { typedef T type; };


template< class T > struct remove_volatile             { typedef T type; };
template< class T > struct remove_volatile<volatile T> { typedef T type; };

我无法理解指针类型推导的规则。 你们能告诉我编译器可能做的方式吗? 是否有扣除规则?

1 个答案:

答案 0 :(得分:2)

根据描述,这些类删除最顶层的 cv限定符。

在他们修改的内容的右侧编写限定符可以帮助解释这一点(^标记最高级别):

int const volatile
    ^
int* const volatile
     ^
int const volatile*
                   ^

在最后一个例子中,顶级没有cv-qualifiers,所以没有什么可以删除。

cv-conversions的详细信息在[conv.qual]中,尽管它并不是特别容易理解。它的要点是:

  • 顶级cv-qualifer可以隐式转换为任意组合
  • 在任何其他级别,必须保留cv-qualifiers(如果存在)
  • 必须将
  • const添加到cv限定符不同的级别之上的每个级别。

该标准提供了一个很好的示例,说明最后一条规则如何防止无意中更改const个对象:

int main() {
  const char c = 'c';
  char* pc;
  const char** pcc = &pc; // #1: not allowed
  *pcc = &c;
  *pc = 'C';              // #2: modifies a const object
}

上述pcc的声明无效,因为最低级别的cv-qualifers不同。为了有效,它必须在冲突之上的每个级别添加额外的const(尽管不一定是最高级别):

const char* const* pcc = &pc;

这可以扩展到必要的级别,以及volatile:

char** pc;
const char*** pcc = &pc;             // Invalid
const char* const* const* pcc = &pc; // Ok

char** pc;
char* volatile** pcc = &pc;          // Nope
char* volatile* const* pcc = &pc;    // OK