不明确的调用:int为double或bool

时间:2014-08-12 20:33:24

标签: c++ overloading template-function

我有一个Parameter类,我重载了构造函数以接受bools或double。当你给它一个int时,它无法构建:

  

错误C2668:'参数::参数':对重载的模糊调用   功能可以   '参数::参数(std :: string,std :: string,double)'或
  '参数::参数(的std :: string,的std :: string,布尔)'

我相信我有两个选择:

  1. 使用int default进行重载
  2. 将我的变量显式转换为double
  3. 我有大量的参数,其中一些是无符号长,浮点数等(在多人支持的项目中),所以这些都不是完美的解决方案。有没有办法强制从int到double的隐式转换?感谢。

    代码:

    #include <string>
    #include <unordered_map>
    using namespace std;
    
    class Parameter
    {
    public:
        enum eVarType { BOOL, NUMBER};
    
        Parameter() {};
        Parameter( string param_name, string param_description, bool dft ) { type_ = BOOL;};
        Parameter( string param_name, string param_description, double dft ) { type_ = NUMBER;};
    private:
        eVarType type_;
    };
    
    class ParameterManager
    {
    public:
        template<typename T> void add( string option_name, string description, T value );
    private:
        std::unordered_map< string, Parameter > parameters;
    };
    
    template<typename T> void ParameterManager::add( string param, string description, T value )
    {
        parameters[param] = Parameter( param, description, value );
    };
    
    int main()
    {
        ParameterManager mgr;
        int var = 1;
        mgr.add("number","This is an int",var); //Could be double or bool: I want it to be a double
    }
    

3 个答案:

答案 0 :(得分:3)

如果您要删除考虑bool最终元素的ctor,除非它是明确的bool,请考虑模板和SFINAE:

template<class X>
Parameter( string , string , X  ,
    enable_if_t<is_same<decay_t<X>, bool>::value, int> = 0)
{ type_ = BOOL;}

See here in context on coliru

或者也许在模板参数列表中执行SFINAE:

template<class X,
    enable_if_t<is_same<decay_t<X>, bool>::value, nullptr_t> = nullptr>
Parameter( string , string , X ) { type_ = BOOL;}

没有enable_if_tdecay_t

template<class X>
Parameter( string , string , X ,
    typename enable_if<is_same<typename decay<X>::type,
    bool>::value, int>::type = 0)
{ type_ = BOOL;}
template<class X,
    typename enable_if<is_same<typename decay<X>::type,
    bool>::value, nullptr_t>::type = nullptr>
Parameter( string , string , X)
{ type_ = BOOL;}

答案 1 :(得分:1)

您可以使用traits模板实现此操作,以使正确的强制转换为双倍。

#include <string>
#include <unordered_map>
using namespace std;

class Parameter
{
public:
    enum eVarType { BOOL, NUMBER };

    Parameter() {};
    Parameter(string param_name, string param_description, bool dft) { type_ = BOOL; };
    Parameter(string param_name, string param_description, double dft) { type_ = NUMBER; };
private:
    eVarType type_;
};

// Traits definitions.
template<typename T> struct DFTtrait;

template<> struct DFTtrait<double> 
{typedef double Type;};

template<> struct DFTtrait<bool>
{typedef bool Type;};

// Here is the key. When it receives an int
// the type is set to double.
template<> struct DFTtrait<int>
{typedef double Type;};



class ParameterManager
{
public:
    template<typename T, typename cast_t = DFTtrait<T>::Type> void add(string option_name, string description, T value);
private:
    std::unordered_map< string, Parameter > parameters;
};

template<typename T, typename cast_t> void ParameterManager::add(string param, string description, T value)
{
    parameters[param] = Parameter(param, description, (cast_t)value);
};



int main()
{
    ParameterManager mgr;
    int var = 1;
    mgr.add("number", "This is an int", var); // Now DFTtrait<T>::Type is evaluated to double
                                              // hence, (cast_t)value == (double)value when T == int
}

这非常适合您的场景:我有大量的参数,其中一些是无符号长,浮点数等... 非常容易添加更多特征(DFTtrait实现)来匹配您的所有需求,例如,如果您添加:

template<> struct DFTtrait<long long int>
{typedef double Type;};

您的代码会自动支持long long int并对double进行适当的转换。

答案 2 :(得分:-1)

一个非常简单的版本是使用模板参数到构造函数,bool的非模板重载(以及您不想转换为double的任何其他类型):

Parameter( string param_name, string param_description, bool dft ) { type_ = BOOL;}
// note, no trailing semicolon required for inline method definitions

template<typename T>
Parameter( string param_name, string param_description, T dft )
{ 
    type_ = NUMBER;
    value = static_cast<double>(dft);
}

(可能是“真实代码”实际上对dft执行了某些操作)。

如果类型不能转换为double,则会出现编译错误。

其他答案使用此技术的更高级版本,允许您T仅匹配某些类型(与我的版本相比,它匹配每种类型但如果使用无效类型则会出错)