Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用模板可变模板参数作为专用参数_C++_Templates_C++11_Variadic Templates - Fatal编程技术网

C++ 使用模板可变模板参数作为专用参数

C++ 使用模板可变模板参数作为专用参数,c++,templates,c++11,variadic-templates,C++,Templates,C++11,Variadic Templates,我的标题可能是错的——如果是这样,请纠正我,但在某个时刻,我很难跟踪我真正想要实现的元东西;) 我有一个类函数模板,如下所示: template<template<typename...> class MapType> Expression Expression::substitute(MapType<std::string, Expression> const& identifierToExpressionMap) const {

我的标题可能是错的——如果是这样,请纠正我,但在某个时刻,我很难跟踪我真正想要实现的元东西;)

我有一个类函数模板,如下所示:

template<template<typename...> class MapType>
    Expression Expression::substitute(MapType<std::string, Expression> const& identifierToExpressionMap) const {
        return SubstitutionVisitor<MapType>(identifierToExpressionMap).substitute(something);
    }
MSVC似乎没有把
MapType
作为一个类型放在一起,我在这里遗漏了什么吗

所以我的问题是

  • 这是否可能,只是MSVC中的一个bug,或者
  • 有没有更简单的方法。请记住,还有许多其他类接收
    MapType
    参数,并使用不同的键/值类型实例化自己的版本

  • 这可能归结为:

    template<class T, class U = int>
    struct cat {};
    
    template< template<class...> class Animal >
    void foo()
    {
        Animal<int> x; (void)x; // (A)
    }
    
    int main()
    {
        foo<cat>();
    }
    
    模板
    结构cat{};
    模板<模板类动物>
    void foo()
    {
    动物x;(无效)x;/(A)
    }
    int main()
    {
    foo();
    }
    
    clang++和g++接受这个看起来很天真的小程序,但MSVC2013更新1不接受


    第(A)行是有问题的:我认为在这个示例中,当传递类template
    cat
    时,模板参数
    Animal
    应该有两个模板参数

    似乎clang++和g++支持为第(A)行中的该模板参数使用默认模板参数,而MSVC不支持

    我不知道标准是否要求他们中的任何一个;例如,见


    在我看来,支持默认模板参数确实很有用,因为(正如在当前版本中所说的)标准库的类模板可能有额外的模板参数(带有默认参数);如果你想直接使用它们作为模板模板参数,你就需要知道这些实现细节。

    给出了已经发生的讨论,我想也许是时候考虑一下工作了。由于推断模板参数似乎是当前的问题,因此放松对MapType的要求可能会有所帮助

    template< typename MapType>
    Expression Expression::substitute( MapType const& identifierToExpressionMap) const {
        return SubstitutionVisitor<MapType>(identifierToExpressionMap).substitute(something);
    }
    
    模板
    表达式::替换(MapType常量和identifierToExpressionMap)常量{
    返回替换访问者(identifierToExpressionMap)。替换(某物);
    }
    
    调用方将被编译为调用函数的代码,因此编译器将推断模板参数,因此基本上您将使用正确的std::map或std::unordered_映射的责任推给调用方

    现在,至少在大多数情况下,这可能有效。但是,可以传入某种类型的容器,该容器可以编译,但实际上没有正确的类型。因此,理想情况下,您仍然需要某种编译时检查,以确保支持MapType(即std::map或std::unordered_map)


    这可以通过Boost概念实现,甚至可以只使用两个模板化的别名声明—如果您可以确保别名声明只提供两种版本:map或unordered\u map,请使用enable\u。

    当MSVC不同意GCC和Clang时,这是MSVC中的一个错误。不幸的是,我现在没有VS2013要测试,但是因为没有太多的回复,所以这里有一些可以测试的东西:充实函数替换上的参数,为map的模板提供两个默认参数(std::less和std::allocator)。然后让substitute的调用者尝试传入一个指定了其所有模板参数的映射(即:它有std::less和std::allocator)。这里的测试是为了看看如果在每个步骤中都显式地显示所有模板参数,VS是否处理得更好。@qeadz但是无序的_映射比映射有更多的模板参数-并且我无法通过std::map并将所有参数指定到替换中,因为它不再是一个模板,我需要在类中使用不同的键/值类型-也许我不明白你的建议…?@qeadz我想你提到了一个重要的问题:
    std::map
    类模板实际上有四个模板参数,所以当用作模板参数时,它应该需要所有四个模板参数来实例化(因为默认参数不会传递给模板参数)。然而,有些例子是用clang++和g++编译的,不知道为什么。哇。。。这似乎是一个悬而未决的问题:我接受了另一个答案,因为这里描述了实际的原因和问题,所以对于任何有类似问题的人来说,这可能对我更有用。很抱歉,你们俩都有很好的见解。
    template< typename MapType>
    Expression Expression::substitute( MapType const& identifierToExpressionMap) const {
        return SubstitutionVisitor<MapType>(identifierToExpressionMap).substitute(something);
    }