gpt4 book ai didi

c++ - 这被认为是有效的 c++11 或 c++14 吗?还是 gcc/clang 弄错了?

转载 作者:可可西里 更新时间:2023-11-01 17:44:25 26 4
gpt4 key购买 nike

在尝试解决 Is it possible to tell if a class has hidden a base function in C++? 时,我生成了这个:

#include <type_traits>
#include <iostream>

#define ENABLE_IF(...) std::enable_if_t<(__VA_ARGS__), int> = 0

template<class T, class B, ENABLE_IF(std::is_same<void(T::*)(), decltype(&T::x)>::value)>
auto has_x_f(T*) -> std::true_type;

template<class T, class B>
auto has_x_f(B*) -> std::false_type;

template<class T, class B>
using has_x = decltype(has_x_f<T, B>((T*)nullptr));

template<typename T>
struct A
{
void x() {}

static const bool x_hidden;

template <typename R, ENABLE_IF(std::is_same<T, R>::value && x_hidden)>
void y(R value)
{
std::cout << "x() is hidden" << std::endl;
}

template <typename R, ENABLE_IF(std::is_same<T, R>::value && !x_hidden)>
void y(R value)
{
std::cout << "x() is not hidden" << std::endl;
}

//using t = std::integral_constant<bool, x_hidden>;
};

struct B : A<B>
{
void x() {}
};

struct C : A<C>
{
};

template<typename T>
const bool A<T>::x_hidden = has_x<T, A<T>>::value;

int main()
{
B b;
C c;

std::cout << "B: ";
std::cout << b.x_hidden << std::endl;
std::cout << "C: ";
std::cout << c.x_hidden << std::endl;

std::cout << "B: ";
b.y(b);
std::cout << "C: ";
c.y(c);

return 0;
}

输出我想要的:

B: 1C: 0B: x() is hiddenC: x() is not hidden

clanggcc都“正确”地编译和执行它,但是 vc++不会(尽管我知道它在使用类似于 template <typename T> ... decltype(fn(std::declval<T>().mfn())) 的表达式时存在问题)。

所以我的问题是,这被认为是有效的还是以后会失效?我也很好奇 x_hidden能够在函数中用作模板参数但不能在using t = std::integral_constant<bool, x_hidden> 中使用它.这仅仅是因为模板的类型此时没有完全声明吗?如果是这样,为什么将它用于函数声明?

最佳答案

如果x_hidden为假,不存在此模板函数的模板参数

template <typename R, ENABLE_IF(std::is_same<T, R>::value && x_hidden)>
void y(R value) {
std::cout << "x() is hidden" << std::endl;
}

可以实例化,因此您的程序格式错误,无需诊断。这是一种常见的黑客攻击,其非法性可能会在某些时候变得明确甚至合法。

使用 has_x_f 可能是有原因的而不是直接初始化 is_hiddenis_same子句,但它未在您的代码中演示。

对于任何模板特化,必须有使实例化有效的参数。如果没有,则程序格式错误,无需诊断。

我相信这个条款在标准中允许编译器对模板进行更高级的检查,但并不要求它们。

template <typename R, ENABLE_IF(std::is_same<T, R>::value && x_hidden)>
void y(R value)
{
std::cout << "x() is hidden" << std::endl;
}

编译器可以随意通知x_hiddenfalse ,然后说“is_same<T,R> 是什么并不重要”,并推断没有模板参数可以使这个特化有效。然后产生错误。

一个简单的破解方法是

template <class T2=T, class R,
ENABLE_IF(std::is_same<T2, R>::value && has_x<T2, A<T2>>::value)
>
void y(R value)
{
std::cout << "x() is hidden" << std::endl;
}

我们在其中偷偷添加了另一个模板参数,等于 T通常。现在,编译器必须承认 T2 的可能性。通过 has_x测试,传递的参数是R .用户可以通过手动传递“错误的” T2 来绕过这个.

这可能无法解决所有问题。该标准在这里阅读起来有点棘手,但一种阅读指出,如果在 y() 的主体内我们去假设我们的 T本身有x() , 我们仍然违反了有效模板实例化可能性的规则。

[temp.res] 14.6/8(root 和 1)

Knowing which names are type names allows the syntax of every template to be checked. The program is ill-formed, no diagnostic required, if:

  • no valid specialization can be generated for a template [...] and the template is not instantiated, or

没有有效的特化

template <typename R, ENABLE_IF(std::is_same<T, R>::value && x_hidden)>
void y(R value)
{
std::cout << "x() is hidden" << std::endl;
}

可以生成如果 x_hidden是假的。另一个过载的存在是无关紧要的。

如果您使用 T2 修复它技巧,同样的规则适用如果 body 假设T=T2 .

标准中有三个词试图不导致模板在某些上下文中被实例化,但我不确定这是否使上述代码格式正确。

关于c++ - 这被认为是有效的 c++11 或 c++14 吗?还是 gcc/clang 弄错了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43749115/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com