C++ 未能正确推断GCC中可变类型和非类型模板参数包的混合

C++ 未能正确推断GCC中可变类型和非类型模板参数包的混合,c++,c++11,gcc,c++14,variadic-templates,C++,C++11,Gcc,C++14,Variadic Templates,好了,伙计们,我尝试最小化以下代码来说明我遇到的问题。它看起来相当糟糕,并且省略了许多原始代码。虽然不一定与我遇到的问题相关,但我正在尝试实现一种依赖注入机制。我试图设计它,使从已经依赖注入的类派生的类能够从各自的父类继承依赖关系。如果需要,我可以提供完整的代码,但是这个更简单的版本足以产生问题 #include <tuple> #include <type_traits> template<typename ... Dependencies> class

好了,伙计们,我尝试最小化以下代码来说明我遇到的问题。它看起来相当糟糕,并且省略了许多原始代码。虽然不一定与我遇到的问题相关,但我正在尝试实现一种依赖注入机制。我试图设计它,使从已经依赖注入的类派生的类能够从各自的父类继承依赖关系。如果需要,我可以提供完整的代码,但是这个更简单的版本足以产生问题

#include <tuple>
#include <type_traits>

template<typename ... Dependencies>
class DependencyInjectable
{
public:

    typedef DependencyInjectable<Dependencies ...> tDependencies;
    typedef tDependencies tDependencyInjectable;
    typedef std::tuple<Dependencies ...> tTuple;
    static const constexpr size_t Depth = 0;

    template<typename Arg, typename DecayArg = typename std::decay<Arg>::type, typename ... Args,
             typename = std::enable_if_t<!std::is_same<DecayArg, bool>::value>>
    DependencyInjectable(Arg &&arg, Args && ... args) { }

    virtual ~DependencyInjectable(void) { }
};

template<typename T> struct tuple_as_dependency_injectable_type { };
template<typename ... Args> struct tuple_as_dependency_injectable_type<std::tuple<Args ...>>
{
    typedef DependencyInjectable<Args ...> type;
};

template<typename T> struct dependencies_of { typedef T type; };

template<typename Dependency, typename ... Dependencies>
class DependencyInjectable<dependencies_of<Dependency>, Dependencies ...>
    : virtual public Dependency::tDependencyInjectable,
    public tuple_as_dependency_injectable_type<decltype(std::tuple_cat(std::declval<
                                                        typename Dependency::tDependencyInjectable::tTuple>(),
                                                        std::declval<std::tuple<Dependencies ...>>()))>::type
{
public:

    template<typename Arg, bool = Arg::Depth != 0, typename ... Args>
    struct get_virtual_bases
    {
        typedef typename Arg::tBase T;
        typedef typename get_virtual_bases<T, T::Depth != 0,
            typename Arg::tDependencyInjectable, Args ...>::type type;
    };

    template<typename Arg, typename ... Args>
    struct get_virtual_bases<Arg, false, Args ...>
    {
        typedef std::tuple<typename Arg::tDependencyInjectable, Args ...> type;
    };

    typedef decltype(std::tuple_cat(std::declval<typename Dependency::tDependencyInjectable::tTuple>(),
                     std::declval<std::tuple<Dependencies ...>>())) tTuple;
    typedef typename tuple_as_dependency_injectable_type<tTuple>::type tDependencies;
    typedef DependencyInjectable<dependencies_of<Dependency>, Dependencies ...> tDependencyInjectable;
    typedef Dependency tBase;
    static const constexpr auto Depth = 1 + std::tuple_size<typename get_virtual_bases<tBase>::type>::value;

    template<typename Arg, typename ... Args, typename std::enable_if<
        !std::is_same<typename std::decay<Arg>::type, decltype(std::make_index_sequence<Depth - 1>{ })>::value, int>::type = 0>
        DependencyInjectable(Arg &&arg, Args && ... args)
        : DependencyInjectable(std::make_index_sequence<Depth - 1>{ }, std::make_index_sequence<1 + sizeof ... (Args)> { },
                               std::forward_as_tuple(arg, std::forward<Args>(args) ...)) { }

private:

    template<typename ... Args, size_t ... IndicesOne, size_t ... IndicesTwo>
    DependencyInjectable(const std::index_sequence<IndicesOne ...> &, const std::index_sequence<IndicesTwo ...> &,
                         const std::tuple<Args ...> &tuple)
        : std::tuple_element<IndicesOne, typename get_virtual_bases<
        typename Dependency::tDependencyInjectable>::type>::type(std::get<IndicesTwo>(tuple) ...) ...,
        tDependencies(std::get<IndicesTwo>(tuple) ...) { }

public:

    virtual ~DependencyInjectable(void) { }
};
#包括
#包括
模板
类依赖可注入
{
公众:
类型定义依赖性可注射tDependencies;
typedef tdependencys tDependencyInjectable;
typedef std::tuple tTuple;
静态常数constexpr size\u t Depth=0;
模板>
DependencyInjectable(Arg&&Arg,Args&&Args){}
虚~DependencyInjectable(void){}
};
模板结构元组作为依赖项可注入类型{};
模板结构元组作为依赖项可注入类型
{
typedef依赖注入型;
};
{typedef T type;}的模板结构依赖项;
模板
类依赖可注入
:虚拟公共依赖项::tDependencyInjectable,
公共元组作为依赖项可注入类型(),
std::declval())>::类型
{
公众:
模板
结构获取虚拟基
{
typedef typename Arg::tBase T;
typedef typename get_virtual_base::type type;
};
模板
结构获取虚拟基
{
typedef std::元组类型;
};
typedef decltype(std::tuple_cat(std::declval(),
std::declval()))t对;
typedef typename tuple_as_dependency_injectable_type::type tDependencies;
类型依赖性可注射tDependencyInjectable;
typedef依赖性tBase;
静态常量constexpr auto Depth=1+std::tuple\u size::value;
模板::类型=0>
DependencyInjectable(Arg&&Arg,Args&&Args)
:DependencyInjectable(std::make_index_sequence{},std::make_index_sequence{},
std::forward作为元组(arg,std::forward(args)…){
私人:
模板
DependencyInjectable(常数std::index_序列&,常数std::index_序列&,
常量std::元组和元组)
:std::tuple_元素::type>::type(std::get(tuple)。。。,
tDependencies(std::get(tuple)…{}
公众:
虚~DependencyInjectable(void){}
};
以下是测试该类的代码段:

struct DependencyOne { };
struct DependencyTwo { };

class DependentClassOne
: virtual public DependencyInjectable<DependencyOne *>
{
public:

    DependentClassOne(const tDependencies &dependencies) : tDependencyInjectable(dependencies) { }
    virtual ~DependentClassOne(void) { }
};

class DependentClassTwo
: public DependentClassOne,
  virtual public DependencyInjectable<dependencies_of<DependentClassOne>, DependencyTwo *>
{
public:
    DependentClassTwo(const tDependencies &dependencies)
    : tBase(dependencies),
      tBase::DependencyInjectable(dependencies),
      tDependencyInjectable(dependencies) { }

    virtual ~DependentClassTwo(void) { }
};

int main(int argc, char **argv)
{
    DependencyOne dependencyOne;
    DependencyTwo dependencyTwo;

    auto &&tuple = std::make_tuple(&dependencyOne, &dependencyTwo);

    DependentClassOne dependentClassOne(tuple);
    DependentClassTwo dependentClassTwo(tuple);

    return 0;
}
struct DependencyOne{};
结构依赖性二{};
类依赖项类
:虚拟公共依赖项可注入
{
公众:
DependentClassOne(const tDependencies&dependencies):tDependencyInjectable(dependencies){}
虚~DependentClassOne(void){}
};
类dependentClass2
:public DependentClassOne,
虚拟公共依赖项可注入
{
公众:
DependentClassThou(常量tDependencies&dependencies)
:t数据库(依赖项),
tBase::DependencyInjectable(依赖项),
tDependencyInjectable(依赖项){}
虚~DependentClassTwo(void){}
};
int main(int argc,字符**argv)
{
依赖一个依赖一个;
依赖二依赖二;
auto&&tuple=std::make_tuple(&dependencyOne和&dependencyTwo);
DependentClassOne DependentClassOne(元组);
DependentClassThound DependentClassThou(元组);
返回0;
}
使用GCC 6.3.0编译此代码会产生以下错误:

: In instantiation of 'DependencyInjectable<dependencies_of<Dependency>, Dependencies ...>::DependencyInjectable(std::index_sequence<IndicesOne ...>&, std::index_
sequence<IndicesTwo ...>&, const std::tuple<_Args1 ...>&) [with Args = {const DependencyInjectable<DependencyOne*, DependencyTwo*>&}; long long unsigned int ...IndicesOne = {0ull}; long long unsigned
int ...IndicesTwo = {0ull}; Dependency = DependentClassOne; Dependencies = {DependencyTwo*}; std::index_sequence<IndicesOne ...> = std::integer_sequence<long long unsigned int, 0ull>; std::index_seque
nce<IndicesTwo ...> = std::integer_sequence<long long unsigned int, 0ull>]':
:63:88:   required from 'DependencyInjectable<dependencies_of<Dependency>, Dependencies ...>::DependencyInjectable(Arg&&, Args&& ...) [with Arg = const Dependency
Injectable<DependencyOne*, DependencyTwo*>&; Args = {}; typename std::enable_if<(! std::is_same<typename std::decay<Arg>::type, decltype (typename std::_Make_integer_sequence<long long unsigned int, (
DependencyInjectable<dependencies_of<Dependency>, Dependencies ...>::Depth - 1), typename std::_Build_index_tuple<(DependencyInjectable<dependencies_of<Dependency>, Dependencies ...>::Depth - 1)>::__t
ype>::__type{})>::value), int>::type <anonymous> = 0; Dependency = DependentClassOne; Dependencies = {DependencyTwo*}]'
:99:41:   required from here
:72:54: error: no matching function for call to 'DependencyInjectable<DependencyOne*>::DependencyInjectable(bool)'
         tDependencies(std::get<IndicesTwo>(tuple) ...) { }
                                                      ^
:16:5: note: candidate: template<class Arg, class DecayArg, class ... Args, class> DependencyInjectable<Dependencies>::DependencyInjectable(Arg&&, Args&& ...)
     DependencyInjectable(Arg &&arg, Args && ... args) { }
     ^~~~~~~~~~~~~~~~~~~~
:16:5: note:   template argument deduction/substitution failed:
:5:7: note: candidate: constexpr DependencyInjectable<DependencyOne*>::DependencyInjectable(const DependencyInjectable<DependencyOne*>&)
 class DependencyInjectable
       ^~~~~~~~~~~~~~~~~~~~
:5:7: note:   no known conversion for argument 1 from 'bool' to 'const DependencyInjectable<DependencyOne*>&'
:在'DependencyInjectable::DependencyInjectable(std::index_sequence&,std::index'的实例化中_
序列&,常数std::tuple&[带Args={const DependencyInjectable&};long long unsigned int…指示符one={0ull};long long unsigned
int…IndicesTwo={0ull};Dependency=dependentclasson;Dependency={DependencyTwo*};std::index_sequence=std::integer_sequence;std::index_sequence
nce=std::整数_序列]':
:63:88:从'DependencyInjectable::DependencyInjectable(Arg&&,Args&&…[带Arg=const Dependency]中需要
可注入&;Args={};typename std::enable_if::type=0;Dependency=DependentClassOne;dependencitytwo*}
:99:41:从这里开始需要
:72:54:错误:调用“DependencyInjectable::DependencyInjectable(bool)”时没有匹配的函数
tDependencies(std::get(tuple)…{}
^
:16:5:注意:候选:模板DependencyInjectable::DependencyInjectable(Arg&&,Args&&…)
DependencyInjectable(Arg&&Arg,Args&&Args){}
^~~~~~~~~~~~~~~~~~~~
:16:5:注意:模板参数扣除/替换失败:
:5:7:注意:候选:constexpr DependencyInjectable::DependencyInjectable(const DependencyInjectable&)
类依赖可注入
^~~~~~~~~~~~~~~~~~~~
:5:7:注意:参数1从'bool'到'const DependencyInjectable&'的转换未知
具体而言,我对GCC为何会发出此错误感到困惑:

:72:54:错误:调用“DependencyInjectable::DependencyInjectable(bool)”时没有匹配的函数 tDependencies(std::get(tuple)…{}

显然,模板参数推断是失败的,但我不知道为什么。'bool'是如何推导出来的?GCC似乎在与以下路线抗争:

typename Dependency::tDependencyInjectable>::type>::type(std::get<IndicesTwo>(tuple) ...) ...,
typename依赖项::tDependencyInjectable>::type>::type(std::get(tuple)。。。,
我特意在基类中添加了以下构造函数来解决这个问题:

template<typename Arg, typename DecayArg = typename std::decay<Arg>::type, typename ... Args,
         typename = std::enable_if_t<!std::is_same<DecayArg, bool>::value>>
DependencyInjectable(Arg &&arg, Args && ... args) { }
模板>
DependencyInjectable(Arg&&Arg,Args&&Args){}
此代码已被Microsoft Visual Studio 14接受并按预期运行。一个稍微不同的版本会编译成叮当声,尽管这个特定的版本可能不会。Clang和Visual Studio都是正确的,或者GCC正确地拒绝了我的代码。我错过了什么?

每当我看到deduc