c++ - 基于数组大小有效性的特化

标签 c++ template-specialization

尝试根据数组大小的有效性进行特化:

// base template
template<int p, typename T = void>
struct absolute {
    operator int () const { return 0; }
};

// positive case template
template<int p>
struct absolute<p, typename std::void_t<int[p]>> {
    operator int () const { return p; }
};

// negative case template
template<int p>
struct absolute<p, typename std::void_t<int[-p]>> {
    operator int () const { return -p; }
};


int main() {
    std::cout << absolute<5>() << std::endl;
    std::cout << absolute<-5>() << std::endl;
    std::cout << absolute<0>() << std::endl;
}

问题#1:

以上代码works nicely with gcc but fails to compile with clang .

Clang 生成错误:重新定义模板结构“绝对”

谁是对的?

问题#2:

Both with gcc and with clang (如果我们移除负面特化以将 clang 带回游戏中),不清楚为什么 absolute<0>()选择基本模板。 There is nothing wrongint[0]以及 std::void_t<int[0]>这似乎更专业:
// base template
template<int p, typename T = void>
struct absolute {
    operator int () const { return -1; }
};

// positive case template
template<int p>
struct absolute<p, typename std::void_t<int[p]>> {
    operator int () const { return p; }
};

int main() {
    std::cout << absolute<5>() << std::endl; // 5
    std::cout << absolute<0>() << std::endl; // -1, why not 0?
}

并且...如果只是在没有实现的情况下声明了基本模板,则为:
// base template
template<int p, typename T = void>
struct absolute;

Both gcc and clang would fail to compile , 投诉 不完整类型的无效使用 电话:absolute<0>() .即使它似乎适合特殊情况。

这是为什么?

最佳答案

关于Clang的重定义错误,见this question .

原来是别名模板的模板id,比如std::void_t将简单地替换为它们的别名类型,而不检查替换失败的参数。这被更改为 CWG issue 1558 .这只是将标准更改为要求在要完成的模板参数中替换失败,但并未阐明在替换别名后是否等效的两个模板是否应被视为等效。 Clang 认为它们是等价的,但 GCC 不是。这是开放的CWG issue 1980 .

-pedantic-errors GCC 已经报告了一个硬错误

std::cout << absolute<5>() << std::endl;

在特化
template<int p>
struct absolute<p, typename std::void_t<int[-p]>>

因为据说数组大小不是常量表达式。数组的大小必须是类型 std::size_t 的转换后的常量表达式.转换后的常量表达式只能使用非缩小转换。所以-p是真的与 p = 5转换为 std::size_t不是常量表达式,使得类型 int[-p]格式错误,但我认为这应该导致替换失败,而不是硬错误。 [temp.deduct/8] C++17 标准(草案 N4659)说:

If a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed, with a diagnostic required, if written using the substituted arguments.



这适用于这里。引用后给出的非规范示例甚至包括负数组大小作为替换失败的示例。

特别奇怪的是对于absolute<-5>() GCC 不报告等效错误
template<int p>
struct absolute<p, typename std::void_t<int[p]>>

特化,其中int[p]将评估为 int[-5]它也没有转换后的常量表达式大小。
absolute<0>()选择主模板,因为数组大小需要大于零,这使得部分特化都不可行。零大小数组是一种语言扩展,可以通过 -pedantic-errors 禁用。在 GCC 和 Clang 中。

关于c++ - 基于数组大小有效性的特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60715854/

相关文章:

c++ - 通过 C++ 从 PKCS7 (CMS) 获取详细信息

c++ - 为什么编译器在定义类似的模板特化时不会报错?

c++ - 如何从 Win32 C++ 应用程序输出到父控制台窗口?

c++ - 如何获得最后一个strtok?

c++ strptime在解析时忽略时区

C++ : using index as template parameter in for loop

C++ 枚举模板偏特化

c++ - std::conditional 如何工作

c++ - const指针专门化可使用MSVC生成未解析的符号,并且适用于GCC/Clang

c++ - 为 SEAL 选择合适的参数并阐明一些数学运算