gpt4 book ai didi

c++ - std::is_assignable::value 在 A 具有可变参数构造函数时始终为真

转载 作者:行者123 更新时间:2023-11-30 00:50:21 24 4
gpt4 key购买 nike

希望问题从问题中显而易见:)如果不是,请考虑以下代码:

template <typename Ty>
class test
{
public:
test(std::string &v) : val(v) {}

template <typename... Args>
test(Args&&... args) : val(std::forward<Args>(args)...) {}

Ty val;
};

int main(void)
{
std::cout << std::is_assignable<test<std::string>, std::string>::value << std::endl;
std::cout << std::is_assignable<test<std::string>, std::vector<int>>::value << std::endl;
}

两种情况下的输出都是正确的,使用 Visual Studio 2013 update 3 和 ideone 进行了测试。在许多不同的层面上,这对我来说似乎是错误的。其一,尝试构造/分配 std::vector<int>test<std::string> 类型的实例不会编译(显然)。我可以接受这一点,因为编译器可能只是检查类型以及是否存在可接受的函数(而不是所述函数是否编译)。

最让我烦恼的是构造函数应该对赋值没有影响。在删除可变参数构造函数时,这似乎是正确的(至少在 GCC 中)。在这两种情况下,输出都是假的。在 Visual Studio 上,输出的第一行仍然为真;我明天会提交一个错误。

无论如何,这是正确的行为吗?这似乎很违反直觉。

最佳答案

这与可变参数构造函数模板没有太大关系。问题是您有一个构造函数模板采用不受约束的通用引用参数。使用以下构造函数还会打印 1在这两种情况下:

template <typename Args>
test(Args&& args) : val(std::forward<Args>(args)) {}

is_assignable的定义是(§20.10.4.3 [meta.unary.prop],表 49):

The expression declval<T>() = declval<U>() is well-formed when treated as an unevaluated operand (Clause 5). Access checking is performed as if in a context unrelated to T and U. Only the validity of the immediate context of the assignment expression is considered. [ Note: The compilation of the expression can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the “immediate context” and can result in the program being ill-formed. —end note ]

这允许使用隐式转换序列。通用引用可以绑定(bind)到一切,因此您的可变参数构造函数定义了从一切test 的隐式转换。 . (您的构造函数采用 std::string & 不会对 is_assignable 产生影响,因为 declval<std::string>() 的返回类型是右值引用,因此不会绑定(bind)到非常量左值引用。)

如果您不希望这种情况发生,请将您的构造函数标记为 explicit .使用 std::is_constructible 来约束可变参数模板构造函数可能也是一个好主意。 :

template <typename... Args, typename = typename std::enable_if<std::is_constructible<Ty, Args...>::value>::type>
explicit test(Args&&... args) : val(std::forward<Args>(args)...) {}

关于c++ - std::is_assignable<A, B>::value 在 A 具有可变参数构造函数时始终为真,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25323026/

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