在以下示例中,GCC >= 4.7
实例化模板构造函数(可通过读取错误消息来观察),但应仅需要隐式生成的复制构造函数。在需要复制构造函数时实例化GCC:模板构造函数
#include <type_traits>
// 'ambiguous' is ambiguous for 'ambiguous<int, int>'
template<typename A, typename B>
struct ambiguous : std::false_type {};
template<typename T>
struct ambiguous<int, T> : std::true_type {};
template<typename T>
struct ambiguous<T, int> : std::true_type {};
// quantity
template<typename Type>
class quantity
{
public:
quantity() = default;
// Copy-constructor is implicitly created
// Template constructor
template<
typename T,
typename = typename std::enable_if<ambiguous<Type, T>::value>::type
>
quantity(quantity<T>) {}
template<
typename T,
typename = typename std::enable_if<ambiguous<Type, T>::value>::type
>
void set(quantity<T>) {}
};
// main
int main()
{
quantity<int> a;
quantity<float> b;
b.set(a);
}
以上代码编译在GCC < 4.7
,clang
和MSVS
(不知道哪个版本,我使用的http://rextester.com/runcode之一)。在GCC >= 4.7
编译失败,出现以下消息:调用b.set(a);
时
main.cpp: In substitution of ‘template<class T, class> quantity<Type>::quantity(quantity<T>) [with T = int; <template-parameter-1-2> = <missing>]’:
main.cpp:39:12: required from here
main.cpp:23:9: error: ambiguous class template instantiation for ‘struct ambiguous<int, int>’
typename = typename std::enable_if<ambiguous<Type, T>::value>::type
^
main.cpp:9:8: error: candidates are: struct ambiguous<int, T>
struct ambiguous<int, T> : std::true_type {};
^
main.cpp:12:8: error: struct ambiguous<T, int>
struct ambiguous<T, int> : std::true_type {};
^
main.cpp: In function ‘int main()’:
main.cpp:31:10: error: initializing argument 1 of ‘void quantity<Type>::set(quantity<T>) [with T = int; <template-parameter-2-2> = void; Type = float]’
void set(quantity<T>) {}
所以,GCC
显然是寻找一个拷贝构造函数,在路上,实例化模板的构造函数这反过来实例ambiguous<int, int>
这是(呃... ...)暧昧。
问题:是GCC
是否有权实例化模板构造函数,即使需要复制构造函数?
很好的回答!还有一个问题:在14.8.2p8的应用中,GCC和clang之间的区别是clang不一定实例化所有模板专业化,或者它将潜在的不合格实例作为“直接上下文”来处理(因此不会导致整个程序不合格)? –
@DaviD。后者 - 如果我们引入一个中间模板 struct V:U
{};那么clang会拒绝该程序,所以它肯定会实例化该模板特化。 – ecatmur