如何定义依赖于模板参数的类型定义



我想做一个typedef,它依赖于模板参数中是否存在typedef

struct foo
{
using MyType = int;
};
template <typename T = foo>
struct bar
{
// Pseudo code
#if T::MyType is defined
using MyType = T::MyType;
#else
using MyType = double;
#endif
};

有没有办法让它使用std::conditional或 C++14 中的其他东西工作?

有,有一点sfinae。

template<class, typename Fallback, typename = void>
struct type_or_default {
using type = Fallback;
};
template<class C, typename F>
struct type_or_default<C, F, std::void_t<typename C::type>> {
using type = typename C::type;
};

这使用标准约定,其中模板元函数type公开成员名称,但您可以根据自己的命名需求对其进行调整。这里唯一的非 C++14 位是std::void_t,但等效的东西可以在 C++14 中实现(只是不能放入命名空间std中)。你在课堂上使用它,就像这样:

template <typename T = foo>
struct bar
{
using type = typename type_or_default<T, double>::type;
};

这里发生的情况是编译器在选择模板专用化时进行模式匹配。如果类C有一个成员type,那么我们提供的部分特化将被视为更专业化,因此被选中。否则(如果在检查专用化时替换失败),则始终可以回退到主模板。

现场节目修补。

我对这个问题有五分钱。

#include <type_traits>
template <typename T, typename DefaultType>
struct CalculateMyType {
template <typename C>
static typename C::MyType test(typename C::MyType*);
template <typename>
static DefaultType test(...);
typedef decltype(test<T>(nullptr)) MyType;
};

struct foo
{
using MyType = int;
};

template <typename T = foo>
struct bar
{
using MyType = typename CalculateMyType<T, double>::MyType;
};

struct baz
{
};
struct quux
{
using MyType = float;
};

#include <iostream>
#include <typeinfo>
template <typename>
struct TypeToStr;
template<> struct TypeToStr<double> { const char * name = "double"; };
template<> struct TypeToStr<float> { const char * name = "float"; };
template<> struct TypeToStr<int> { const char * name = "int"; };
int main() {
std::cout << "bar<foo>::MyType = " << TypeToStr<bar<foo>::MyType>().name << std::endl;
std::cout << "bar<baz>::MyType = " << TypeToStr<bar<baz>::MyType>().name << std::endl;
std::cout << "bar<quux>::MyType = " << TypeToStr<bar<quux>::MyType>().name << std::endl;
}

现场节目

最新更新