【问题标题】:"No Matching Constructor" Error When Trying to Instantiate Object of a Template Class尝试实例化模板类的对象时出现“没有匹配的构造函数”错误
【发布时间】:2018-08-26 02:36:37
【问题描述】:

编辑:

  1. 我很抱歉this 以及在我的模板类末尾缺少;;我在复制和粘贴代码时遇到了一些问题,因此我手动复制了一些代码并将这些部分弄乱了。
  2. 重新打开 IDE 后,错误就神奇地消失了。也许Repl.it 遇到了一些问题。错误信息现在不同了。如果我无法自行解决此错误,我会提出一个新问题。

感谢HugoTeixeira、Matthew Fisher 和user4581301 的周到回复。


我在Group.h中有以下代码:

template <typename T, int N> class Group
{
    public:
        T values[N];

        Group(T args[])
        {
            for (int i = 0; i < N; i++)
            {
                values[i] = args[i];
            }
        }

        Group()
        {
            Group((T[]){0, 0, 0});
        }
};

在main.cpp,我有这个代码:

#include "Group.h"

int main()
{
    Group<double, 3> * v1 = new Group<double, 3>();
}

当我尝试运行此代码时,我的 IDE 给出了错误:

no matching constructor for initialization of 'Group<double, 3>'

我曾尝试编写此代码,但减去了模板,它运行良好。我做错了什么?

【问题讨论】:

  • this((T[]){0, 0, 0}) 没有意义,does not compile。
  • 您在挑选错误消息。在到达main() 之前,至少会诊断出两个错误和一个可能触发警告(全部在头文件中)的可疑代码构造,它们将导致编译器对不带参数的构造函数的存在感到困惑(并因此诊断您报告的错误)。
  • 旁注:将一个包含三个元素的数组放入一个期望N-element 数组的构造函数中是个坏主意。如果T 是std::string 怎么办?零没有多大意义。
  • @user4581301 射击,你是对的。我不知道我在想什么。
  • 请不要在回答后这样编辑问题。如果您愿意,可以发布一个新问题

标签: c++ templates instantiation


【解决方案1】:

您的代码存在一些问题:

调用另一个构造函数:如果你想在 C++ 中调用另一个构造函数,你不能使用 this 关键字(就像在 Java 中一样)。您必须在冒号后执行此操作(又名 initializer list),如下所示:

Group(): Group((T[]){0, 0, 0})
{} 

类定义以分号结尾:在 C++ 中,类定义(无论是否模板化)必须以分号结尾。你忘了把它添加到你的代码中:

class A {
    ...
};  <<--- end with a semi-colon

原始指针:理想情况下,您的代码不应使用原始指针。有一些智能指针可以使您的代码更优雅且更易于维护。例如,您可以使用std::unique_ptr 或std::shared_ptr(视情况而定)。这是 C++14 中的一个简单示例:

auto v1 = std::make_unique<Group<double, 3>>();

【讨论】:

  • 非常感谢您周到而有条理的回答。我在我的问题中犯了一些错别字,结果我收到的错误消息完全是 IDE 的问题。但是,我正在处理的新问题已通过您关于构造函数委托的第一点解决,因此我将其标记为已接受。
  • Group(): Group((T[]){0, 0, 0}) 是标准 C++ 中的语法错误。带括号的类型名称后不能有大括号列表
  • @M.M 很好。我不认为检查复合文字是 C++ 标准不向后兼容 C 的一种情况。但是,GCC 和 Clang 似乎支持它们作为扩展。
【解决方案2】:

我将朝着不同的方向前进,放弃那些 array casts and other dodgy behavior,而选择 std::initializer_list (documentation) 和 delegated constructor。

template <typename T, size_t N>// replaced int with size_t. 
                               //why allow a negative size?
class Group
{
    public:
        T values[N];

        Group(std::initializer_list<T> list)  
        {
            // may be different sizes
            size_t copylen = std::min(list.size(), N); 
            std::copy(list.begin(), 
                      list.begin()+copylen, 
                       values); // copy all we can

            //default initialize remainder, if any
            for (size_t i = copylen; i < N; i++)
            { 
                values[i] = T();
            }
        }
        Group():Group{T()} // might be a cleaner way to do this. 
                           // I don't know it.
        {
        }
/* this may be more efficient. A good compiler can optimize this 
   down to next-to-nothing
        Group()
        {
            for (size_t i = 0; i < N; i++)
            {
                values[i] = T();
            }
        }
*/
};

Documentation for std::copy

通过上述方式,您可以处理更多种类的案件。例如,

int main()
{
    Group<double, 3> v0; //none
    Group<double, 3> v1{1.0}; // too few
    Group<double, 3> v3{1.0, 2.0, 3.0};
    Group<double, 3> v4{1.0, 2.0, 3.0, 4.0}; // too many
    Group<std::string, 3> s2{"A", "B"}; // non-numeric
}

【讨论】:

    【解决方案3】:

    这似乎是编译器的边缘情况。为一种 C++ 编译器而不是另一种编译器编译各种风格。下面的代码适用于 gcc 和 clang。

    template <typename T, int N> class Group
    {
        public:
            T values[N];
    
            Group(T args[])
            {
                for (int i = 0; i < N; i++)
                {
                    values[i] = args[i];
                }
            }
    
            Group()
            {
              Group((T[]){0, 0, 0});
            }
    };
    
    int main()
    {
        Group<double, 3> * v1 = new Group<double, 3>();
    }
    

    【讨论】:

    • 感谢您的回答。我收到的错误消息原来是 IDE 的问题。然而,我不得不面对的新错误是试图从另一个构造函数中调用一个构造函数。你是如何编译的?
    • @NetherGranite 在 Clang 编译器的最新版本中编译。我不知道为什么,但我不声称自己是一名语言律师。可能是语言扩展,或者我正在阅读什么是合法和非法的错误。
    • @user4581301 呵呵,真奇怪。此类功能甚至不是已经存在的标准或即将实施的标准的一部分?
    • @NetherGranite 我很抱歉。我没有注意到马修已经更新了答案,以消除我对以前版本的主要抱怨。新版本似乎无法使用我可以使用的任何编译器进行编译。
    • 最新版本应该可以使用 gcc 和 clang。但是,它看起来与 OP 中的相同。 @NetherGranite 尝试将所有内容放在一个文件中以排除其他不相关的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 2017-02-27
    相关资源
    最近更新 更多