在C中的元编程中,保护从非const-volatile类型到const-volatile的赋值的正确方法是什么?

例如,我有一个实现null_or的函数

template <typename T, typename U>
auto null_or(T *p, U *default_value) ->
    typename std::enable_if<std::is_same<typename std::decay<U>::type,
                                         typename std::decay<T>::type>::value,
                            T *>::type {
  if (p) {
    return p;
  } else {
    return default_value;
  }
}

仅使用std :: decay将使const / volatile类型* default_value分配到非const / non-volatile类型* p.

避免它的最佳方法是什么?

此外,类型default_value [100]的数组类型(具有范围)不能分配给它.怎么解决呢?

可以也可以没有例子:

  const char *s = nullptr;
  char       *s2 = nullptr;

  const char *hello0 = "hello0";
  std::string hello1 = "hello1";
  char        hello2[] = "hello2";
  char        hello3[100] = "hello3";
  int         hello4[] = {1,2,3,4,5,0};

  const char *ss = nullptr;

  // const char * ==> const char *, OK
  ss = null_or(s, hello0);
  printf("%s\n", ss);

  // std::string ==> const char *, no conversion at all, Bad
  // ss = null_or(s, hello1);
  // printf("%s\n", ss);

  // char [7] ==> const char *, OK
  ss = null_or(s, hello2);
  printf("%s\n", ss);

  // char [100] ==> const char *, OK
  ss = null_or(s, hello3);
  printf("%s\n", ss);

  // int [6] ==> const char *, Bad
  // ss = null_or(s, hello4);
  // printf("%s\n", ss);

  // const char * ==> char *, const pointer stuffs should not be assigned to non consts, Bad
  // ... also, const reference should not be assigned to non const references for some other generic algorithms
  // ss = null_or(s2, hello0);
  // printf("%s\n", ss);

  // std::string ==> char *, no version at all, Bad
  // ss = null_or(s2, hello1);
  // printf("%s\n", ss);

  // char [7] ==> char *, OK
  ss = null_or(s2, hello2);
  printf("%s\n", ss);

  // char [100] ==> char *, OK
  ss = null_or(s2, hello3);
  printf("%s\n", ss);

  // int [6] ==> char *, Bad
  // ss = null_or(s2, hello4);
  // printf("%s\n", ss);

还有很多其他通用算法只需要简单的概念检查右侧是否可以安全地分配到左侧,所以我想知道是否有更通用的解决方案.

最佳答案 您的示例在需要时已经失败,但根据null_or定义.

您可以将声明更改为

template <typename T, typename U>
auto null_or(T *p, U *default_value)
-> typename std::enable_if<std::is_assignable<T*&, U*>::value,
                           T *>::type

到SFINAE那些错误.

点赞