我想指定一個類的模板轉換運算符的模板參數,但我似乎無法得到正確的語法。在http://liveworkspace.org/code/35sqXe$4C++如何指定一個類的模板轉換運算符的參數
#include <iostream>
using namespace std;
class C
{
int i_;
public:
C(int i) : i_(i) {}
template<int adder> int get() { return i_ + adder; }
template<int adder> int operator()() { return i_ + adder; }
template<int adder> operator int() { return i_ + adder; }
// If I add a default argument to operator int()'s adder template parameter this compiles fine
// (of course, I still can't figure out how to specify it...)
};
int main(int, char*[])
{
C c(10);
cout << c.get<2>() << endl; // I can specify template argument here the regular way.
// cout << c() << endl; // No template argument specified, so I wouldn't have expected this to work.
cout << c.operator()<3>() << endl; // We have to call it this way.
// cout << (int)c << endl; // In the same vein I wouldn't expect this to work either.
cout << c.operator int<4>() << endl; // But how do I specify template argument here? This seems to be an error for some compilers.
return 0;
}
相同的代碼當與克++ 4.7.2
$ g++ -std=c++11 -Wall -W -pedantic "template conversion operator.cpp"
Compilation finished with errors:
source.cpp: In function 'int main(int, char**)':
source.cpp:23:23: error: 'int' is not a template
source.cpp:23:30: error: no matching function for call to 'C::operator int()'
source.cpp:23:30: note: candidate is:
source.cpp:11:24: note: template<int adder> C::operator int()
source.cpp:11:24: note: template argument deduction/substitution failed:
source.cpp:23:30: note: couldn't deduce template parameter 'adder'
當與G ++ 4.8.0(20130224)
$ g++ -std=c++11 -Wall -W -pedantic "template conversion operator.cpp"
Compilation finished with errors:
source.cpp: In function 'int main(int, char**)':
source.cpp:23:23: error: 'int' is not a template
cout << c.operator int<4>() << endl;
^
source.cpp:23:30: error: no matching function for call to 'C::operator int()'
cout << c.operator int<4>() << endl;
^
source.cpp:23:30: note: candidate is:
source.cpp:11:24: note: template<int adder> C::operator int()
template<int adder> operator int() { return i_ + adder; }
^
source.cpp:11:24: note: template argument deduction/substitution failed:
source.cpp:23:30: note: couldn't deduce template parameter 'adder'
cout << c.operator int<4>() << endl;
^
當與編譯鐺++編譯編譯3.2
$ clang++ -std=c++11 -Wall -W -pedantic "template conversion operator.cpp"
Compilation finished with errors:
source.cpp:23:12: error: reference to non-static member function must be called
cout << c.operator int<4>() << endl;
^~~~~~~~~~~~~~
source.cpp:23:30: error: expected expression
cout << c.operator int<4>() << endl;
^
2 errors generated.
當ICC 13.0.1
$ icc -std=c++11 -Wall -W -pedantic "template conversion operator.cpp"
Compilation finished with warnings:
source.cpp(11): warning #488: constant "adder" is not used in declaring the parameter types of function template "C::operator int"
template<int adder> operator int() { return i_ + adder; }
^
其他編譯則警告,國際商會似乎很好地工作。
這些編譯器錯誤?或者它是我的語法問題?
編輯
由於Yakk問我原來的/實際的問題是什麼:
我有一個類PTR(模板上它指的類型),我想有一個轉換的PTR爲constŤ (雖然我知道在這種情況下並不重要),如果T已經是const類型,我希望轉換運算符不在那裏。由於您沒有爲轉換運算符指定返回類型或方法參數,因此我將enable_if作爲方法模板參數的一部分。由於Yakk(和其他問題中的其他人)已發佈,簡單的template <typename = typename std::enable_if<!std::is_const<T>::value>::type>
不起作用,因爲當Ptr被實例化時,T在編譯器獲得此聲明時已知。由於沒有推導出T不存在SFINAE。由於我們知道!is_const<T>::value
是錯誤的,因此沒有「類型」成員,並且聲明無效。使模板依賴於新類型(U),推導出U,然後檢查U與T相同,並且T不是常量,然後生成無效聲明是SFINAE的有效使用,並且可以工作如預期。
template <typename T>
class Ptr
{
template <typename U,
typename = typename std::enable_if<std::is_same<T, U>::value &&
!std::is_const<U>::value>::type>
operator Ptr<const U>() const { return active; }
};
但後來我對自己說,這是一個模板化的成員函數。那些模板參數不必保留默認值,它們可以由實例化該函數的任何人指定。對於任何其他運算符xxx函數,執行此操作的語法是顯而易見的並且有效(請參閱上面的operator())。對於這個例子:
Ptr<const int> ci;
ci.operator Ptr<const int><const int, void>(); // assuming this syntax is valid
空隙(或任何其他類型的有)將指定的轉換運算符的第二個模板參數,並將含有enable_if默認將不被考慮。當我試圖使它不存在時,這將使這種方法存在。
但是gcc,clang和msvc似乎對這個語法有問題。我假設由於轉換運算符拼寫爲operator typename
,因此模板參數會讓編譯器認爲它們是針對typename而不是操作符。
確實有一些解決方法(只包括轉換運算符,當T已經是const時不會轉換爲const T),但這是針對此特定問題的。也許不可能爲轉換運算符指定模板參數,因此,將這些類型推斷/默認是沒問題的。或者也許有一個語法(icc似乎把它...),所以我打開自己,以指定模板參數和實例化方法,我不希望他們的用戶。我已經爲我的具體問題找到了解決方案(在類型確實重要的時候,在轉換運算符的類型檢查中使用static_assert),但這個問題是關於C++語言及其語法的。頂部的類C只是我想要搜索該語法的最簡單方法。
你可以用」不要這樣做。如果您有轉換運算符模板,則其返回類型必須使用該模板中的參數。沒有辦法指定參數。 – Xeo 2013-03-09 01:04:16
我實際上並不想改變返回類型。這是爲了根據類的模板類型「enable_if」轉換運算符的動機。由於我無法將enable_if作爲返回類型或參數的一部分(沒有任何參數),因此我將其作爲模板類型。然後我想知道該模板類型是否在成員的實例中明確指定,如果轉換操作符不應該出現在類中,那麼是否可以使轉換操作符出現在類中。但我無法弄清楚如何指定模板參數。這是我可以想到的搜索該語法的最簡單的方法。 – 2013-03-09 04:21:33
因爲我正在尋找更多的語言,而不是真正解決特定的問題,所以如果不支持這種語法,我將不勝感激指向C++標準的指針(最好是C++ 11)。 – 2013-03-09 04:34:39