【问题标题】:template constructor overloading issue模板构造函数重载问题
【发布时间】:2013-03-04 03:07:11
【问题描述】:

我有一个包含三个构造函数的类模板,其中一个是函数模板。

template<class T>
class TemplateOverLoading
{
public:
    TemplateOverLoading(void){};
    ~TemplateOverLoading(void){};
    //constructor that take reference
    TemplateOverLoading(std::string& qName, T& qValue )
        :   mName(qName),
            mValue( &qValue)
    {
        std::cout << "Reference -> "<< *mValue <<"\n";
    }

    //Template constructor that takes array
    template<class T, int N>
    TemplateOverLoading(std::string& qName, T (&t)[N])
        :   mName(qName),
            mValue(t)
    {
        std::cout << "Array ->\n";
        for(int i = 0; i < N; i++)
            std::cout<< mValue[i];
        std::cout << std::endl;
    }

    //Other constructor that take pointer
    TemplateOverLoading(std::string& qName, T* qValue )
        :   mName(qName),
            mValue( qValue)
    {
        std::cout << "Pointer "<< *mValue <<"\n";
    }
private:
    T*               mValue;
    //T*              mValueArray;
    std::string&    mName;
};

从我的应用程序中,我需要区分引用类型/值、指针和数组并执行特定操作。因此,我决定必须使用不同的构造函数。

我正在尝试通过以下方式调用构造函数:

int init(10);
int intArray[10] = {0,1,2,3,4,5,6,7,8,9};
TemplateOverLoading<int> mInt(std::string("mInt"), init);    
TemplateOverLoading<int> mIntArray( std::string("mIntArray"), intArray );

问题是如果定义了带有指针的构造函数,则永远不会调用数组构造函数。但是,如果我将其注释掉,它会按应有的方式打印数组。

输出:

(when pointer constructor is present)
Reference -> 10
Pointer 0

(when pointer constructor is not present)
Reference -> 10
Array ->
0123456789

所以在语法上是可能的,并且推断数组大小 N 是正确的。

显然,当存在数组构造函数时,我会混淆编译器。因此,我没有让编译器自动推断,而是尝试为数组构造函数指定模板参数,只发现与常规函数不同,模板参数不能具体指定。

我想在数组构造函数中引入一个虚拟参数来区分重载,但它看起来不太好。

还有其他方法可以解决这个问题吗?任何线索表示赞赏。

【问题讨论】:

    标签: c++ templates function-templates constructor-overloading


    【解决方案1】:

    将指针构造函数参数设为T*&amp; qValue

    TemplateOverLoading(std::string& qName, T*& qValue )
        :   mName(qName),
            mValue( qValue)
    {
        std::cout << "Pointer "<< *mValue <<"\n";
    }
    

    通过使其成为对指针的引用,可以防止数组到指针的衰减并选择数组构造函数。

    另外,我看不到你的代码是如何编译的,我看到很多错误:

    你的模板构造函数有一个参数class T,这与类模板的class T冲突:

    template<class T, int N>
        TemplateOverLoading(std::string& qName, T (&t)[N])
    

    这需要改成class T以外的其他东西,例如class U

    template<class U, int N>
            TemplateOverLoading(std::string& qName, U (&t)[N])
    

    您的构造函数也采用 non-const 左值引用,非 const 引用不能绑定到您在构造函数调用中传递的临时对象,即std::string("mIntArray")。您需要将其更改为const std::string&amp; 或按值获取。另外你的成员std::string&amp; mName; 是一个参考,你应该删除那里的&amp;

    【讨论】:

    • @Xymotech:非模板总是比模板更好的匹配,但如果你将它们都设为模板,那么将选择匹配更好的构造函数(see example)。
    • converted as '@Jessse Good' 说,但它给了我编译错误:error C2668: 'TemplateOverLoading::TemplateOverLoading' : 对重载函数的模糊调用 [T=int ] templateoverloading.h(32): 可以是带有 [T=int, U=int] 或 'TemplateOverLoading:: 的 'TemplateOverLoading::TemplateOverLoading(std::string &,U *)' TemplateOverLoading(std::string &,T (&)[10])' with [T=int]
    • @Jesse 很好,不同的编译器似乎对此有不同的解释。我正在使用 VS2008,并且我之前粘贴的代码可以编译。但是,我已经复制粘贴了与您在 liveworkspace 中放置的代码相同的代码,它仍然给出编译错误 2668 -> 对重载函数的模糊调用
    • @jazaman:不,你的编译器是对的,我使用的编译器有错误。代码模棱两可。将U* qValue 更改为const U* qValue 是解决问题的一种方法(但您只能通过构造函数传递const int*)。
    • @jazaman:我想到了一个很好的解决方案,请参阅我的更新答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-13
    • 2021-01-28
    • 1970-01-01
    • 2015-02-27
    相关资源
    最近更新 更多