MSVC 2017-错误-如何将模板类X的模板成员函数声明为嵌套类X :: Y

时间:2018-08-31 09:38:36

标签: c++ class templates visual-c++ nested

我正在尝试获取一个cmake C ++项目,该项目可以编译并与GCC一起运行以与MSVC一起编译。我正在使用VS2017。

我不是我要负责使其与MSVC一起编译的代码的作者。

该项目很大,所以我不确定如何展示MCVE。但是,我将尽力在这里尽力解释:

我收到此错误:

对应于下面的friend类中的sibling_iterator声明。

但是,leftmost_output()node的成员。

node的定义附在下面(参见向下的3/4):

我很确定这是related to the bug in VS related to nested template classes,因为sibling_iteratornode嵌套在另一个模板类中。

我的问题是如何使整个节点类成为朋友,而不是指定特定的成员函数?这样做可能会失败,除非有其他建议值得欢迎。

2 个答案:

答案 0 :(得分:1)

最小的可复制代码是:

#include <map>
template <class T, class T2>
struct relative_iterator : T {};

struct edge : public std::map<int, int>::iterator {};
using T_edge = edge;

class node {
public:

    template <class T_iterable, class T_content>
    class sibling_iterator : public relative_iterator<T_iterable, T_content>
    {
    public:
        friend sibling_iterator<edge, T_edge>  node::leftmost_output();
    //..
    };

    static sibling_iterator<edge, T_edge> leftmost_output();  // <--move up
} ;

有两种解决方法:

选项1

leftmost_output()上的class sibling_iterator的定义移到

选项2

使node为从属名称。如果name有一个依赖于T_iterable的别名,则其查找将延迟到实例化class sibling_iterator<T_iterable, T_contents>的时间。最简单的方法是在标准中使用标准实用程序:

class sibling_iterator : public relative_iterator<T_iterable, T_content>
{
public:
    static constexpr bool dependent_true = std::is_same<T_iterable,T_iterable>::value;
    using dependent_node = typename std::enable_if<dependent_true, node>::type;
    friend sibling_iterator<edge, T_edge>  dependent_node::leftmost_output();
};

选项2.5

但是,如果您想定义自己的解决方案,则可以定义dependet_type<T, Dependent>助手:

template <class T, class Dependent>
struct dependent_type
{
    using type = T;
};
template <class T, class Dependent>
using dependent_type_t = typename dependent_type<T, Dependent>::type;

并使用它:

template <class T_iterable, class T_content>
class sibling_iterator : public relative_iterator<T_iterable, T_content>
{
public:
    using dependent_node = typename dependent_type<node, T_iterable>::type;
    friend sibling_iterator<edge, T_edge>  dependent_node::leftmost_output();
//..
};

我认为这是最好的选择,因为它需要对现有代码库进行较少的更改。

选项2.5.5

我会写一个简短的变体:

friend sibling_iterator<edge, T_edge> dependent_type_t<node, T_iterable>::leftmost_output()

这看起来很完美,因为它需要对源代码进行最少的更改。如果没有使编译器崩溃,我会写的:

fatal error C1001: An internal error has occurred in the compiler.
(compiler file 'msc1.cpp', line 1469)

答案 1 :(得分:0)

  

我收到此错误:

     

错误C2039:'leftmost_output':不是'mv :: graph :: node'的成员

     

[...]

     

但是,leftmost_output()是节点的成员。

     

节点的定义附在下面(参见方法的3/4)   下):

很明显,VC编译器找不到node的定义,因为它所指的是不同范围的东西。尝试将朋友声明移到嵌套node类的定义下方。