[英]explicit template parameter specification for ostream& operator<< puzzling compile error
我有以下代码:
#include <iostream>
//#include <algorithm> // compile error when `g++ -std=c++11`, fine otherwise
using namespace std;
template<typename T>
class Foo
{
T x_;
public:
Foo(const T& x={}): x_(x){}; // default ctor, bounded rvalue default-initialized
template<typename S>
friend ostream& operator<<(ostream& lhs, const Foo<S>& rhs)
{
return lhs << rhs.x_;
}
};
int main()
{
Foo<double> foo(10.1);
cout << foo << endl;
operator<<(cout, foo) << endl;
//puzzling compile-time error when #include<algorithm> and compile
// with `g++ -std=c++11`, otherwise fine (both clang++ and g++)
operator<< <double>(cout, foo) << endl;
}
但是,如果我#include<algorithm>
并使用g++ -std=c++11
编译,那么编译和编译工作正常,我会得到一个非常混乱的编译错误(参见下文,与std::uniform_int_distribution
?!?!) 。 它发生在最后一行,当我明确指定调用operator<<
的类型double
。
无论-std=c++11
标志如何,它都适用于clang++
,也适用于没有-std=c++11
标志的g++
。 这里发生了什么? 我真的不知道,我是否在某种程度上超载全局<<
在algorithm
定义? 这是一个g++
错误吗? (我使用g ++ 4.9 btw)。
In file included from /opt/local/include/gcc49/c++/random:49:0,
from /opt/local/include/gcc49/c++/bits/stl_algo.h:66,
from /opt/local/include/gcc49/c++/algorithm:62,
from /Users/vlad/minimal.cpp:2:
/opt/local/include/gcc49/c++/bits/random.h: In instantiation of 'class std::uniform_int_distribution<double>':
/Users/vlad/minimal.cpp:25:34: recursively required by substitution of 'template<class _IntType, class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::uniform_int_distribution<_IntType>&) [with _IntType = double; _CharT = char; _Traits = std::char_traits<char>]'
/Users/vlad/minimal.cpp:25:34: required from here
/opt/local/include/gcc49/c++/bits/random.h:1668:7: error: static assertion failed: template argument not an integral type
static_assert(std::is_integral<_IntType>::value,
^
/opt/local/include/gcc49/c++/bits/random.h: In instantiation of 'class std::geometric_distribution<double>':
/Users/vlad/minimal.cpp:25:34: recursively required by substitution of 'template<class _IntType, class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::geometric_distribution<_IntType>&) [with _IntType = double; _CharT = char; _Traits = std::char_traits<char>]'
/Users/vlad/minimal.cpp:25:34: required from here
/opt/local/include/gcc49/c++/bits/random.h:4010:7: error: static assertion failed: template argument not an integral type
static_assert(std::is_integral<_IntType>::value,
^
/opt/local/include/gcc49/c++/bits/random.h: In instantiation of 'class std::negative_binomial_distribution<double>':
/Users/vlad/minimal.cpp:25:34: recursively required by substitution of 'template<class _IntType, class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::negative_binomial_distribution<_IntType>&) [with _IntType = double; _CharT = char; _Traits = std::char_traits<char>]'
/Users/vlad/minimal.cpp:25:34: required from here
/opt/local/include/gcc49/c++/bits/random.h:4210:7: error: static assertion failed: template argument not an integral type
static_assert(std::is_integral<_IntType>::value,
^
/opt/local/include/gcc49/c++/bits/random.h: In instantiation of 'class std::poisson_distribution<double>':
/Users/vlad/minimal.cpp:25:34: recursively required by substitution of 'template<class _IntType, class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::poisson_distribution<_IntType>&) [with _IntType = double; _CharT = char; _Traits = std::char_traits<char>]'
/Users/vlad/minimal.cpp:25:34: required from here
/opt/local/include/gcc49/c++/bits/random.h:4432:7: error: static assertion failed: template argument not an integral type
static_assert(std::is_integral<_IntType>::value,
^
/opt/local/include/gcc49/c++/bits/random.h: In instantiation of 'class std::binomial_distribution<double>':
/Users/vlad/minimal.cpp:25:34: recursively required by substitution of 'template<class _IntType, class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::binomial_distribution<_IntType>&) [with _IntType = double; _CharT = char; _Traits = std::char_traits<char>]'
/Users/vlad/minimal.cpp:25:34: required from here
/opt/local/include/gcc49/c++/bits/random.h:3779:7: error: static assertion failed: template argument not an integral type
static_assert(std::is_integral<_IntType>::value,
^
/opt/local/include/gcc49/c++/bits/random.h: In instantiation of 'class std::discrete_distribution<double>':
/Users/vlad/minimal.cpp:25:34: recursively required by substitution of 'template<class _IntType, class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::discrete_distribution<_IntType>&) [with _IntType = double; _CharT = char; _Traits = std::char_traits<char>]'
/Users/vlad/minimal.cpp:25:34: required from here
/opt/local/include/gcc49/c++/bits/random.h:5253:7: error: static assertion failed: template argument not an integral type
static_assert(std::is_integral<_IntType>::value,
^
我认为可以归结为:
#include <type_traits>
template<class T>
struct foo
{
static_assert(std::is_integral<T>{}, "T must be integral");
};
template<class T> struct bar {};
template<class T, class Stream>
Stream& operator<<(Stream& p, foo<T> const&);
template<class T, class Stream>
Stream& operator<<(Stream& p, bar<T> const&);
int main()
{
int x;
operator<< <double>(x, 1.0);
}
请注意,在libstdc ++的实现中,显式传递给operator<<
的第一个模板参数用作分发的模板参数(在OP中)。 因此理论上,从operator<<
call to the distribution type的第二个函数参数的隐式转换是可能的。
在检查歧义之前,重载解析必须实例化类模板以检查转换构造函数:如果存在任何,如果它们是明确的等 - 也就是说,如果转换是可行的 。
然而,实例化非整数类型的类模板是一个错误,由static_assert
检查。 因此,在选择其中一个重载之前,编译器会抱怨实例化。
如果编译器不需要它来选择重载,则不严格要求此实例化,请参见[temp.inst] / 7。 所有其他重载都需要用户定义的转换(参数类型是一个类,与参数类型不同),而在OP中定义为友元函数的重载是完全匹配。 因此,不需要检查那些其他转换的可行性,无论如何都不会选择那些重载。
不实例化不需要的类模板是某种优化 - 它不是强制性的。 clang ++似乎在这里执行它,g ++没有(并实例化类模板)。 有关另一个示例和一些讨论,请参阅gcc和clang之间的C ++不一致
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.