我想指定一个类的模板转换运算符的模板参数,但我似乎无法得到正确的语法。在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