使用模板和decltype无效使用不完整类型

时间:2014-08-13 17:06:04

标签: c++ templates gcc decltype

我需要做以下工作。

这是我实际代码的简化版本,但基本上难度相同,即推断出工厂方法的返回类型。

具体来说,我需要DeduceObjectT的第二个或第三个变体(两个都已注释),而不是第一个,需要FactoryT::ObjectT typedef。

#include <string>
#include <utility>
#include <memory>

template<class FactoryT>
using DeduceObjectT = typename FactoryT::ObjectT;
//template<class FactoryT>
//using DeduceObjectT = typename decltype(std::declval<FactoryT>().create())::element_type;
//template<class FactoryT>
//using DeduceObjectT = typename std::result_of<decltype(&FactoryT::create)(FactoryT)>::type::element_type;

template<class FactoryT>
struct FactoryUser
{
    typedef DeduceObjectT<FactoryT> ObjectT;
};

template<class FactoryUserT>
struct Foo
{
    typedef typename FactoryUserT::ObjectT ObjectT;
};

struct StringFactory
{
    typedef std::string ObjectT; // want to omit this

    std::unique_ptr<std::string> create()
    {
        return nullptr;
    }

    Foo<FactoryUser<StringFactory>> t;
};

int main()
{
    StringFactory f;
    return 0;
}

经过多次尝试后,我仍然遇到错误:无效使用不完整类型'struct StringFactory'&#39;。

我还尝试通过FactoryUser的默认模板参数推断出类型。

我真的不明白,为什么我得到错误,因为触发所有模板实例化的点就在最后 - 声明数据成员t的行。

编译器是gcc 4.7.3。使用-std = c ++ 0x -O0

2 个答案:

答案 0 :(得分:1)

尝试这样的事情:

template <typename Factory>
struct ProductTypedef
{
  typedef typename decltype(std::declval<Factory>().create())::element_type ObjectT;
};

struct StringFactory : public ProductTypedef<StringFactory> // CRTP
{
    std::unique_ptr<std::string> create()
    {
        return nullptr;
    }
};

答案 1 :(得分:1)

您可以稍微更改Foo以使代码正常工作:

#include <string>
#include <utility>
#include <memory>

template<class FactoryT>
using DeduceObjectT = typename FactoryT::ObjectT;

template<class FactoryT>
struct FactoryUser
{
    typedef DeduceObjectT<FactoryT> ObjectT;
};

// Provide a way for ObjectType to be specified at the time 
// the template is instantiated.
template<class FactoryUserT, typename ObjectType = typename FactoryUserT::ObjectT>
struct Foo
{
    typedef ObjectType ObjectT;
};

struct StringFactory
{
    std::unique_ptr<std::string> create()
    {
        return nullptr;
    }

    Foo<FactoryUser<StringFactory>, std::string> t;
};

int main()
{
   StringFactory f;
   return 0;
}