构造继承与失败的boost ::多precision :: mpz_int [英] Constructor inheritance failure with boost::multiprecision::mpz_int

查看:144
本文介绍了构造继承与失败的boost ::多precision :: mpz_int的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个类从派生的boost ::多precision :: mpz_int ,并把它继承​​基类的构造函数:

I tried to create a class deriving from boost::multiprecision::mpz_int and to have it inherit the base class constructors:

#include <boost/multiprecision/gmp.hpp>

using namespace boost::multiprecision;

struct Integer:
    mpz_int
{
    using mpz_int::mpz_int;
};

G ++ 4.9.0给我以下错误

main.cpp:8:20: error: 'template<class tag, class Arg1, class Arg2, class Arg3, class Arg4> Integer::Integer(const boost::multiprecision::detail::expression<tag, Arg1, Arg2, Arg3, Arg4>&)' inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'
     using mpz_int::mpz_int;
                    ^
main.cpp:8:20: error: conflicts with version inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'
main.cpp:8:20: error: 'template<class Other, boost::multiprecision::expression_template_option ET> Integer::Integer(const boost::multiprecision::number<Backend, ExpressionTemplates>&)' inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'
main.cpp:8:20: error: conflicts with version inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'
main.cpp:8:20: error: 'template<class Other, boost::multiprecision::expression_template_option ET> Integer::Integer(const boost::multiprecision::number<Backend, ExpressionTemplates>&)' inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'
main.cpp:8:20: error: conflicts with version inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'
main.cpp:8:20: error: 'template<class V> Integer::Integer(const V&)' inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'
main.cpp:8:20: error: conflicts with version inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'
main.cpp:8:20: error: 'template<class V> constexpr Integer::Integer(const V&)' inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'
main.cpp:8:20: error: conflicts with version inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'
main.cpp:8:20: error: 'template<class V> Integer::Integer(const V&)' inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'
main.cpp:8:20: error: conflicts with version inherited from 'boost::multiprecision::number<boost::multiprecision::backends::gmp_int>'

事实是,我不知道为什么会这样。下面的解决方法实现了什么,我想做的事:

The truth is that I have no idea why this is happening. The following workaround achieves what I want to do:

struct Integer:
    mpz_int
{
    template<typename... Args>
    Integer(Args&&... args):
        mpz_int(std::forward<Args>(args)...)
    {}
};

任何人都可以解释为什么第一个例子产生错误?我认为继承基类构造函数和值转发给他们做了大致相同的事情。我想我错了,但我仍然有兴趣知道的差异。

Can anybody explain why the first example produces an error? I thought that inheriting the base class constructors and forwarding values to them did roughly the same thing. I guess I was wrong, but I'm still interested in knowing the difference.

编辑:我把事情说清楚。我不在乎的所有的是否有更好的方法来实现这一点(有吨)。我问的唯一的事情就是构造继承在这种情况下失败。这是由于编译器故障或一些模糊的规则某处的标准?

I will make things clear. I don't care at all whether there are better methods to achieve this (there are tons). The only thing I asked is why constructor inheritance failed in this case. Is it due to a compiler bug or to some obscure rule somewhere in the standard?

推荐答案

这似乎是由的的默认参数 mpz_int 的构造 mpz_int 是一个typedef为升压的特定实例::多precision ::号),它用于SFINAE(例如,给定一个模板&LT ;类V&GT; 构造采取常量V&安培; ,选择一个构造函数,如果 V 满足条件X和其他构造,如果 V 满足条件Y)。

This appears to be caused by the default parameters of mpz_int's constructors (mpz_int is a typedef for a particular instantiation of boost::multiprecision::number), which are used for SFINAE (for instance, given a template <class V> constructor taking a const V &, select one constructor if V satisfies criteria X and another constructor if V satisfies criteria Y).

一个小的摄制是:

#include <type_traits>
struct foo {
    template<class T>
    foo(T , typename std::enable_if<std::is_integral<T>::value>::type * = nullptr) { }
    template<class T>
    foo(T , typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr) { }
};

struct bar : foo {
    using foo::foo;
};

int main() { }

在铛编译,但不是G ++ ,生产同样的错误。 (值得注意的是,虽然铛编译上面的摄制code,它实际上并没有,如果你的工作尝试使用继承的构造带一个参数,这是几乎同样糟糕。你可以把它在铛工作,但是,通过的明确提供第二个参数。)

This compiles in clang but not g++, producing the same error. (It's worth noting that while clang compiles the repro code above, it doesn't actually work if you try to use the inherited constructor with a single argument, which is almost equally as bad. You can make it work in clang, however, by explicitly supplying the second parameter.)

我们甚至可以跳过的构造函数的templateness 通过简单的使用,而不是:

We can even skip the templateness for foo's constructors by simply using instead:

struct foo {
    foo(double, int = 0) { }
    foo(double, double = 0) { }
};

和仍然得到同样的结果 - 用g ++错误,OK在铛

and still get the same result - error in g++, OK in clang.

现在,问题是是否该构建事实上应该根据标准被接受。不幸的是,目前还没有明确的答案。 §12.9[class.inhctor] / P1说,

Now, the question is whether this construct should in fact be accepted according to the standard. Unfortunately, there is no clear answer. §12.9 [class.inhctor]/p1 says that

A using声明的(7.3.3)名称构造隐
  声明一组的的继承构造的。在候选集
  继承构造
的从类 X 在命名
  的 using声明的实际组成构造函数和名义构造,从默认的转换结果的
  参数如下:

A using-declaration (7.3.3) that names a constructor implicitly declares a set of inheriting constructors. The candidate set of inherited constructors from the class X named in the using-declaration consists of actual constructors and notional constructors that result from the transformation of defaulted parameters as follows:


      
  • X ,以及所有非模板构造

  •   
  • X 至少有一个参数使用默认的参数,集合构造的每个非模板的构造函数,
      从漏报任何一个省略号参数规范成果,
      先后省略参数与最终默认参数
      在参数类型列表中

  •   
  • X的所有构造函数模板

  •   
  • X 至少有一个参数有默认参数,一组构造函数模板导致的每一个构造函数模板
      从漏报任何一个省略号参数规范并先后
      从底了默认参数省略参数
      参数类型列表

  •   
  • all non-template constructors of X, and
  • for each non-template constructor of X that has at least one parameter with a default argument, the set of constructors that results from omitting any ellipsis parameter specification and successively omitting parameters with a default argument from the end of the parameter-type-list, and
  • all constructor templates of X, and
  • for each constructor template of X that has at least one parameter with a default argument, the set of constructor templates that results from omitting any ellipsis parameter specification and successively omitting parameters with a default argument from the end of the parameter-type-list.

问题是,标准实际上并没有指明会发生什么,如果这个先后,省略参数与 - 默认参数在两个构造函数具有相同签名的过程结果。 (注意:上述的两个模板的构造,省去使用默认参数的参数给出了签名模板&LT;类T&GT;美孚(T); )。虽然第7段中有一张纸条,上面写着

The problem is that the standard doesn't actually specify what happens if this successively-omitting-parameters-with-default-arguments procedure result in two constructors with the same signature. (Note that with both template constructors of foo above, omitting the parameter with default argument gives the signature template<class T> foo(T);.) While paragraph 7 has a note that says

如果两个使用-声明的声明继承与构造
  同样的签名,该计划是非法的构造(9.2,13.1),因为
  由最先推出的隐式声明的构造
  的 using声明的是不是用户声明的构造,因此不会preclude构造的另一份声明具有相同
  通过后来的 using声明的签名

If two using-declarations declare inheriting constructors with the same signatures, the program is ill-formed (9.2, 13.1), because an implicitly-declared constructor introduced by the first using-declaration is not a user-declared constructor and thus does not preclude another declaration of a constructor with the same signature by a subsequent using-declaration.

在这里,我们只有一个的 using声明的,所以说明不适用,而重复的声明确实是禁止的,这是值得商榷的参照的设置第1款意味着重复签名将被简单地视为一个,使单一的 using声明的不会引入重复的声明。

here we have only one using-declaration, so the note doesn't apply, and, while duplicate declarations are indeed prohibited, it is arguable that the reference to a set in paragraph 1 means that duplicate signatures will simply be treated as one, so that a single using-declaration will not introduce a duplicate declaration.

这问题其实是对两个标准的缺陷报告的主题: CWG 1645 CWG 1941年,目前还不清楚这些缺陷报告将如何解决。一种可能性,在CWG问题1645 2013注所指出的,是使这种继承的构造函数(即从多个基构造函数来了)删除,使他们产生只用时出错。另一种方法在CWG问题提出1941年是要继承的构造函数表现得像引入派生类的其他基类的功能。

This issue is in fact the subject of two defect reports against the standard: CWG 1645 and CWG 1941, and it is unclear how those defect reports will be resolved. One possibility, noted in the 2013 note in CWG issue 1645, is to make such inherited constructors (that came from multiple base constructors) deleted, so that they cause an error only when used. An alternative approach suggested in CWG issue 1941 is to make inheriting constructors behave like other base class functions introduced into the derived class.

这篇关于构造继承与失败的boost ::多precision :: mpz_int的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆