C++ gcc vs.clang:“;“不完整类型的无效使用”;使用std::declval和模板专门化
我有一个方法C++ gcc vs.clang:“;“不完整类型的无效使用”;使用std::declval和模板专门化,c++,c++11,gcc,clang,sfinae,C++,C++11,Gcc,Clang,Sfinae,我有一个方法fun,它包含在用于部分专门化的结构Impl中。检查是否派生自\u模板用于确定泛型Impl::fun是否可用于派生自特定模板的类型。否则,Impl将显式地部分专用化 #include <iostream> template <typename T, typename U> struct Base{}; // Forward declaration struct Foo; struct Bar; template <template<typen
fun
,它包含在用于部分专门化的结构Impl
中。检查是否派生自\u模板
用于确定泛型Impl::fun
是否可用于派生自特定模板的类型。否则,Impl
将显式地部分专用化
#include <iostream>
template <typename T, typename U>
struct Base{};
// Forward declaration
struct Foo;
struct Bar;
template <template<typename...> class T, typename U>
struct is_derived_from_template
{
private:
template<typename... Args>
static decltype(static_cast<const T<Args...>&>(std::declval<U>()), std::true_type{}) test(const T<Args...>&);
static std::false_type test(...);
public:
static constexpr bool value = decltype(test(std::declval<U>()))::value;
};
template <typename T, typename = void>
struct Impl
{
static void fun(T& x);
};
template <typename T>
struct Impl<T, typename std::enable_if<is_derived_from_template<Base, T>::value>::type>
{
static void fun(T& base)
{
std::cout << "Base" << std::endl;
}
};
template <>
void Impl<Foo>::fun(Foo& t)
{
std::cout << "Foo" << std::endl;
}
struct Foo {};
struct Bar : Base<int,double> {};
int main()
{
Foo foo;
Bar bar;
Impl<Foo>::fun(foo);
Impl<Bar>::fun(bar);
}
1.
Clang
的编译方式与传统编译器(如GCC
)略有不同GCC
是正确的,因为与Clang
相比,它“传统地”解析代码,并且您应该在使用它们之前定义类型。你可以找到一个比较 2.更改:
// Forward declaration
struct Foo;
struct Bar;
致:
structfoo{};
结构条:基{};
为我工作。1.
Clang
的编译方式与传统编译器(如GCC
)略有不同GCC
是正确的,因为与Clang
相比,它“传统地”解析代码,并且您应该在使用它们之前定义类型。你可以找到一个比较 2.更改:
// Forward declaration
struct Foo;
struct Bar;
致:
structfoo{};
结构条:基{};
为我工作。减少到
#include <utility>
void f(...);
class C;
using type = decltype(f(std::declval<C>()));
尽管您应该谨慎,不允许使用不完整的类型实例化is_derived_from_template
,因为如果完整的类型是从指定的模板派生的,则很容易导致ODR冲突。减少到
#include <utility>
void f(...);
class C;
using type = decltype(f(std::declval<C>()));
尽管您应该谨慎,不允许使用不完整的类型实例化is_derived_from_template
,因为如果完整的类型是从指定的模板派生的,则很容易导致ODR冲突
#include <utility>
void f(...);
class C;
using type = decltype(f(std::declval<C>()));
template <template<typename...> class T, typename U>
struct is_derived_from_template
{
private:
template<typename... Args>
static decltype(static_cast<const T<Args...>&>(std::declval<U>()), std::true_type{}) test(const T<Args...>*);
static std::false_type test(...);
public:
static constexpr bool value = decltype(test(std::declval<U*>()))::value;
};