6

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

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

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

任何帮助将不胜感激

#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
}

编译器错误是:

example.cpp:在构造函数 'Store3Items::Store3Items(const T1&, const T2&, const T3&) [with T1 = std::basic_string, T2 = char [12], T3 = int]' 中:
example.cpp:50:50: 从 'StoreItemsBase* CreateHolder(const T1&, const T2&, const T3&) [with T1 = std::basic_string, T2 = char [12], T3 = int]'
example.cpp:65:74: 从这里实例化
example.cpp:21:11: error: array used as initializer
4

2 回答 2

7

您可以使用元函数来转换作为参数传递给模板的类型。任何字符数组都将转换为char*

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;
};

然后,不是Tn直接使用,而是使用typename transform< Tn >::type.

更新:如果你在C++11中工作,那么std::decay你已经做了你想要的。

于 2012-05-17T23:58:44.157 回答
1

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

根据模板参数决定函数参数通常很困难。你可以试试这个类构造函数签名。我使用类“arg_type”(非标准)的模板特化来确保所有不是 const 指针的参数类型都由 const ref 传递,并且所有 const 指针都作为 const 指针传递。

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

#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
}

请记住,您的类将在内部存储原始 const char*(不存储 std::string),因此请确保传入的字符串的范围比您存储的指针寿命更长。像你的例子中的常量字符串很好,因为它们永远存在。

于 2012-05-18T01:07:27.800 回答