2012-05-17 70 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),所以確保傳入的字符串的範圍比存儲的指針長。像你的例子中的常量字符串很好,因爲它們永遠活着。