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 - Fatal编程技术网

C++ 在模板函数中将常量字符[]自动转换为常量字符*

C++ 在模板函数中将常量字符[]自动转换为常量字符*,c++,templates,C++,Templates,我在模板方面遇到了一些问题,如果您尝试给模板化函数一个字符串参数,编译器会将“Hello World”解释为const char[12]。我希望它是const char* 我可以通过将每个字符串静态转换为“const char*”来“解决”这个问题,但由于我正试图将其作为日志系统的一部分使用,因此简化它是一个很大的目标 由于很难解释我的意思,我想出了一个简单的复制机。您将看到主函数的最后一行没有编译 任何帮助都将不胜感激 #include <string> // Trivial b

我在模板方面遇到了一些问题,如果您尝试给模板化函数一个字符串参数,编译器会将“Hello World”解释为const char[12]。我希望它是const char*

我可以通过将每个字符串静态转换为“const char*”来“解决”这个问题,但由于我正试图将其作为日志系统的一部分使用,因此简化它是一个很大的目标

由于很难解释我的意思,我想出了一个简单的复制机。您将看到主函数的最后一行没有编译

任何帮助都将不胜感激

#include <string>

// Trivial base class so we can use polymorphism
class StoreItemsBase
{
public:
    StoreItemsBase() {}
};

// Example of a trivial Templated class to hold some 3 items.
// Intent to have similar classes to hold 4,5..n items
template <typename T1, typename T2, typename T3>
class Store3Items : public StoreItemsBase
{
public:
    Store3Items(const T1& t1, const T2& t2, const T3& t3)
    :
    StoreItemsBase(),
    mT1(t1),
    mT2(t2),
    mT3(t3)
    {}

private:
    T1 mT1;
    T2 mT2;
    T3 mT3;
};

// Function to create a pointer to our object with added id
// There would be similar CreateHolderFunctions for 4,5..n items
template <typename T1, typename T2, typename T3>
StoreItemsBase* CreateHolder(const T1& t1, const T2& t2, const T3& t3)
{
    return new Store3Items<T1, T2, T3>(t1, t2, t3);
}

int main()
{
    int testInt=3;
    double testDouble=23.4;
    const std::string testStr("Hello World");

    StoreItemsBase* Ok1 = CreateHolder(testInt, testDouble, testStr);
    StoreItemsBase* Ok2 = CreateHolder(testDouble, testStr, testInt);
    StoreItemsBase* Ok3 = CreateHolder(testStr, static_cast<const char*>("Hello there"), testInt);
    // If you try a standard string, it compiler complains
    // Although I could surround all my strings with the static cast, what I am looking for is a way
    // to for the CreateHolder function to do the work for me
    StoreItemsBase* NotOk4 = CreateHolder(testStr, "Hello World", testInt);

    // Free our objects not shown in the example
}
#包括
//简单的基类,因此我们可以使用多态性
类StoreItemsBase
{
公众:
StoreItemsBase(){}
};
//一个普通模板类的示例,用于保存大约3项。
//打算有类似的类别来容纳4,5..n个项目
模板
类别Store3Items:公共StoreItemsBase
{
公众:
存储3个项目(常数T1和T1、常数T2和T2、常数T3和T3)
:
StoreItemsBase(),
mT1(t1),
mT2(t2),
mT3(t3)
{}
私人:
T1-mT1;
T2-mT2;
T3 mT3;
};
//函数创建指向添加id的对象的指针
//对于4,5..n项,将有类似的CreateHolderFunction
模板
StoreItemsBase*CreateHolder(常数T1和T1、常数T2和T2、常数T3和T3)
{
返回新的Store3项目(t1、t2、t3);
}
int main()
{
int-testInt=3;
双重测试双重=23.4;
const std::string testStr(“Hello World”);
StoreItemsBase*Ok1=CreateHolder(testInt、testDouble、testStr);
StoreItemsBase*Ok2=CreateHolder(testDouble、testStr、testInt);
StoreItemsBase*Ok3=CreateHolder(testStr,static_cast(“你好”),testInt);
//如果您尝试使用标准字符串,编译器会抱怨
//虽然我可以用静态的演员阵容来包围我所有的琴弦,但我要寻找的是一种方法
//为了让CreateHolder函数为我做这项工作
StoreItemsBase*NotOk4=CreateHolder(testStr,“Hello World”,testInt);
//释放示例中未显示的对象
}
编译器错误为:

example.cpp: In constructor ‘Store3Items::Store3Items(const T1&, const T2&, const T3&) [with T1 = std::basic_string, T2 = char [12], T3 = int]’: example.cpp:50:50: instantiated from ‘StoreItemsBase* CreateHolder(const T1&, const T2&, const T3&) [with T1 = std::basic_string, T2 = char [12], T3 = int]’ example.cpp:65:74: instantiated from here example.cpp:21:11: error: array used as initializer example.cpp:在构造函数“Store3Items::Store3Items(常数T1&,常数T2&,常数T3&)[带T1=std::basic_字符串,T2=char[12],T3=int]”中: 示例.cpp:50:50:从“StoreItemsBase*CreateHolder(常数T1&,常数T2&,常数T3&)[带T1=std::basic_字符串,T2=char[12],T3=int]实例化” 示例.cpp:65:74:从此处实例化 示例.cpp:21:11:错误:数组用作初始值设定项
可以使用元函数将作为参数传递的类型转换为模板。任何字符数组都将转换为
字符*

template< typename T > struct transform
{
    typedef T type;
};

template< std::size_t N > struct transform< char[N] >
{
    typedef char* type;
};
template< std::size_t N > struct transform< const char[N] >
{
    typedef const char* type;
};
template结构转换
{
T型;
};
模板结构转换
{
typedef char*类型;
};
模板结构转换
{
typedef const char*类型;
};
然后,您将使用
typename转换::type
,而不是直接使用
Tn


更新:如果您使用的是C++11,则
std::decay
已经完成了所需的操作。

尝试将模板参数更改为常量T1 T1、常量T2 T2、常量T3。它的性能会降低,但可以编译

根据模板参数确定函数参数通常很困难。您可以尝试将其用于类构造函数签名。我使用类“arg_type”(非标准)的模板专门化来确保所有不是常量指针的参数类型都由const ref传递,所有常量指针都作为常量指针传递

另外,不要忘记基类上的虚拟析构函数,否则可能会发生不好的事情:)

#包括
//简单的基类,因此我们可以使用多态性
类StoreItemsBase
{
公众:
StoreItemsBase(){}
虚拟~StoreItemsBase(){}
};
模板类参数类型
{
公众:
typedef const TYPE&TYPE;
};
模板类参数类型
{
公众:
类型定义常量类型*类型;
};
//一个普通模板类的示例,用于保存大约3项。
//打算有类似的类别来容纳4,5..n个项目
模板
类别Store3Items:公共StoreItemsBase
{
typedef typename arg_type::type arg1;
typedef typename arg_type::type arg2;
typedef typename arg_type::type arg3;
公众:
存储3个项目(arg1 t1、arg2 t2、arg3 t3)
:
StoreItemsBase(),
mT1(t1),
mT2(t2),
mT3(t3)
{}
私人:
T1-mT1;
T2-mT2;
T3 mT3;
};
//函数创建指向添加id的对象的指针
//对于4,5..n项,将有类似的CreateHolderFunction
模板
StoreItemsBase*CreateHolder(常数T1、常数T2、常数T3)
{
返回新的Store3项目(t1、t2、t3);
}
int main()
{
int-testInt=3;
双重测试双重=23.4;
const std::string testStr(“Hello World”);
StoreItemsBase*Ok1=CreateHolder(testInt、testDouble、testStr);
StoreItemsBase*Ok2=CreateHolder(testDouble、testStr、testInt);
StoreItemsBase*Ok3=CreateHolder(testStr,static_cast(“你好”),testInt);
//如果您尝试使用标准字符串,编译器会抱怨
//虽然我可以用静态的演员阵容来包围我所有的琴弦,但我要寻找的是一种方法
//为了让CreateHolder函数为我做这项工作
StoreItemsBase*NotOk4=CreateHolder(testStr,“Hello World”,testInt);
//释放示例中未显示的对象
}

请记住,您的类将在内部存储一个原始const char*(而不是存储一个std::string),因此请确保传入的字符串的作用域将比您存储的指针的寿命更长。像您的示例中那样的常量字符串很好,因为它们永远存在。

const char[]与const char*不同。虽然直接强制转换可以隐式进行,但反过来则不行。这就像想要将父类强制转换为其子类。一般来说,请包含编译器错误消息-即使专家也能更详细地回答您的问题
#include <string>

// Trivial base class so we can use polymorphism
class StoreItemsBase
{
public:
    StoreItemsBase() {}
    virtual ~StoreItemsBase() {}
};

template <typename TYPE> class arg_type
{
public:
    typedef const TYPE& type;
};
template <typename TYPE> class arg_type<const TYPE*>
{
public:
    typedef const TYPE* type;
};

// Example of a trivial Templated class to hold some 3 items.
// Intent to have similar classes to hold 4,5..n items
template <typename T1, typename T2, typename T3>
class Store3Items : public StoreItemsBase
{
    typedef typename arg_type<T1>::type arg1;
    typedef typename arg_type<T2>::type arg2;
    typedef typename arg_type<T3>::type arg3;
public:
    Store3Items(arg1 t1, arg2 t2, arg3 t3)
    :
    StoreItemsBase(),
    mT1(t1),
    mT2(t2),
    mT3(t3)
    {}

private:
    T1 mT1;
    T2 mT2;
    T3 mT3;
};

// Function to create a pointer to our object with added id
// There would be similar CreateHolderFunctions for 4,5..n items
template <typename T1, typename T2, typename T3>
StoreItemsBase* CreateHolder(const T1 t1, const T2 t2, const T3 t3)
{
    return new Store3Items<T1, T2, T3>(t1, t2, t3);
}

int main()
{
    int testInt=3;
    double testDouble=23.4;
    const std::string testStr("Hello World");

    StoreItemsBase* Ok1 = CreateHolder(testInt, testDouble, testStr);
    StoreItemsBase* Ok2 = CreateHolder(testDouble, testStr, testInt);
    StoreItemsBase* Ok3 = CreateHolder(testStr, static_cast<const char*>("Hello there"), testInt);
    // If you try a standard string, it compiler complains
    // Although I could surround all my strings with the static cast, what I am looking for is a way
    // to for the CreateHolder function to do the work for me
    StoreItemsBase* NotOk4 = CreateHolder(testStr, "Hello World", testInt);

    // Free our objects not shown in the example
}