2012-05-17 68 views
4

我在与模板,由此,如果你试图给一个模板函数的字符串参数,编译器的“Hello World”作为为const char [12]的问题。我希望它是const char *。自动转换为const char []为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 
} 

编译错误是: example.cpp:在构造“Store3Items :: Store3Items(常量T1 &,常量T2 &,常量T3 &)[用T1 = std :: basic_string,T2 = char [12],T3 = int]':T1351 = std :: basic_string,T2 = char [12],T3 = int]' exampl e.cpp:65:74:从这里实例化 example.cpp:21:11:error:用作初始化程序的数组

+0

const char []与const char *不同。尽管直接投射可能是隐含的,但反过来却不是。这就像是想要将一个父类投给它的孩子。 –

+0

一般来说,请包含编译器错误信息 - 即使专家将能够更快地回答您的问题。 – ndkrempel

+1

P.S. char []和char *具有不同的语义 - 是否要Store3Items存储字符串的副本或指向原始字符串的指针? – ndkrempel

回答

5

您可以使用元函数将作为参数传递的类型转换为模板。字符的任意阵列将被转化为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已经做你想要什么。

+0

更好地使用专门化使其成为'std :: string'也许? – AJG85

+0

我不相信这是有效的(我试着将它作为答案),因为你不能用'变换 :: type mT2'替换'T2 mT2;'。请参阅http://stackoverflow.com/questions/10645085/using-a-member-type-of-templated-class-as-the-type-of-a-class-member-variable – Zero

+0

为什么不使用'std: :衰变<>'?如果OP希望这种C字符串的行为,那么也可能用于其他类型的行为。 – ildjarn

0

尝试改变模板参数为const T1 T1,T2常量T2,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),所以确保传入的字符串的范围比存储的指针长。像你的例子中的常量字符串很好,因为它们永远活着。