Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何制作C++;模板化函数与未来专门化的返回类型无关_C++_Function_Templates_C++11 - Fatal编程技术网

C++ 如何制作C++;模板化函数与未来专门化的返回类型无关

C++ 如何制作C++;模板化函数与未来专门化的返回类型无关,c++,function,templates,c++11,C++,Function,Templates,C++11,我想要一个通用的模板函数声明,我不知道(已经)它的返回类型,类似于: **template <class T> auto getIds() noexcept -> std::vector<Any>;** **template auto getIds()noexcept->std::vector** 然后,可以使用几个输入类型和基于它的返回类型专门化函数: template <> auto getIds<MyClass>() noexcep

我想要一个通用的模板函数声明,我不知道(已经)它的返回类型,类似于:

**template <class T> auto getIds() noexcept -> std::vector<Any>;**
**template auto getIds()noexcept->std::vector**
然后,可以使用几个输入类型和基于它的返回类型专门化函数:

template <> auto getIds<MyClass>() noexcept -> std::vector<decltype(MyClass::id)>
{
    // implementation here.
}
template auto getIds()noexcept->std::vector
{
//在这里执行。
}
最后调用它而不设置返回:

auto val = getIds<MyClass>();
auto val=getIds();
可能吗?怎么做

注意事项:

#include <iostream>
#include <vector>

template <typename T> struct wrapper { };

template <typename T>
auto getIds() -> decltype(getIds(wrapper<T>{}))
{
    return getIds(wrapper<T>{});
}

template <typename T>
void getIds(wrapper<T> ) { }

struct MyClass {
    int id;
};

std::vector<decltype(MyClass::id)> getIds(wrapper<MyClass> )
{
    return {1, 2, 3};
}

int main()
{
    for (auto id : getIds<MyClass>()) {
        std::cout << id << " ";
    }

}
我要避免的是必须在调用函数中手动设置Id类型:

auto val = getIds<MyClass, decltype(MyClass::id)>(); // Ugly
auto val=getIds();//丑陋的
我还放弃了任何(非基于模板的)解决方案,比如从RootMyClass扩展所有类型。不是这些解决方案不好,而是它们没有抓住问题的关键

尽量说清楚一点:

#include <iostream>
#include <vector>

template <typename T> struct wrapper { };

template <typename T>
auto getIds() -> decltype(getIds(wrapper<T>{}))
{
    return getIds(wrapper<T>{});
}

template <typename T>
void getIds(wrapper<T> ) { }

struct MyClass {
    int id;
};

std::vector<decltype(MyClass::id)> getIds(wrapper<MyClass> )
{
    return {1, 2, 3};
}

int main()
{
    for (auto id : getIds<MyClass>()) {
        std::cout << id << " ";
    }

}
如果我写

class MyClass { public: int id1=4;};
template <class T, class Id> auto getIds() -> Id;
template <> auto getIds<MyClass, decltype(MyClass::id1)>() -> decltype(MyClass::id1)
{
    return 1;
}

auto main() -> int
{
    getIds<MyClass>(); // Do not compile
    getIds<MyClass, decltype(MyClass::id1)>(); // Compile but ugly
}
classmyclass{public:intid1=4;};
模板自动获取Id()->Id;
模板自动获取ID()->decltype(MyClass::id1)
{
返回1;
}
auto main()->int
{
getIds();//不编译
getIds();//编译但不美观
}
我希望返回类型是隐式的,但我没有找到通过专门化实现这一点的方法:

template <class T> getIds() noexcept -> WHICH TYPE?;
template getIds()noexcept->WHICH TYPE?;
这实际上与Haskell TypeClass非常相似,而且,令人惊讶的是,它可以工作。不过,对于实际使用,我会使用函子来允许部分专门化

#include <iostream>

template<typename T> 
decltype(T::x) getX(T const& t) { return; }

class A { public: int x; A(int x):x(x){} };
template<> int getX<A>(A const& a) {
    return a.x;
}

class B { public: std::string x; B(std::string x):x(std::move(x)){}  };
template<> std::string getX<B>(B const& b) {
    return b.x;
}

int main() {
    A a(42);
    B b("43");

    std::cout << getX(a) << std::endl;
    std::cout << getX(b) << std::endl;
}
因此:

class A {
    using TypeOfX = int;
    TypeOfX someComplexLogicToGetX();
};

为实际类型实例化的类型的两种解决方案,除了一种是从字段类型获得的,另一种是从直接的“类型变量”获得的。不幸的是,您不能在专门化中更改返回类型。您可以做的是在不同的重载中更改返回类型。明显地此外,函数模板的专门化比函数重载要复杂得多,所以让我们这样做吧

引入一个空类型包装器,例如:

template <typename T> struct wrapper { };
将通用版本声明为:

template <typename T>
void getIds(wrapper<T> );
最后一个示例:

#include <iostream>
#include <vector>

template <typename T> struct wrapper { };

template <typename T>
auto getIds() -> decltype(getIds(wrapper<T>{}))
{
    return getIds(wrapper<T>{});
}

template <typename T>
void getIds(wrapper<T> ) { }

struct MyClass {
    int id;
};

std::vector<decltype(MyClass::id)> getIds(wrapper<MyClass> )
{
    return {1, 2, 3};
}

int main()
{
    for (auto id : getIds<MyClass>()) {
        std::cout << id << " ";
    }

}
#包括
#包括
模板结构包装{};
模板
auto getIds()->decltype(getIds(包装{}))
{
返回getid(包装{});
}
模板
void getid(包装器){}
结构MyClass{
int-id;
};
std::vector getid(包装器)
{
返回{1,2,3};
}
int main()
{
对于(自动id:getIds()){

std::cout你问的问题还不完全清楚。你只是想知道如何显式地专门化不同返回类型的函数模板吗?不,我问的是在返回未知时如何声明函数模板(将在专门化中已知)。为什么普通函数专用化对您不起作用?它已经允许您具有不同的返回类型。嗯,不允许使用std::vector。如果您没有默认实现,可以将其标记为返回void。无论如何,没有人会调用它。它不使用VS2013编译:-S C2912:显式专用化'int getX(const a&)'不是函数的特化template@AdrianMaire有趣的是,因为。我想知道谁在这里,但叮当一声接受它也让我认为这只是另一个VS编译器问题。可能是,我也不喜欢VS2013,但我不是决定这一点的人。@AdrianMail我想你可以试试第二个版本。VS2013似乎不喜欢它两者都不是:同样的错误。返回值好像是签名的一部分。@T.C.完全忘记了这一点。重写了大部分答案。我正试图用你的答案做一个简单的测试。我必须承认我不完全理解包装类型的概念。第一个getIds函数的尾部返回值是什么?你能添加请求吗一个用C++11编译的简单例子?
std::vector<decltype(MyClass::id)> getIds(wrapper<MyClass> )
{ ... }
#include <iostream>
#include <vector>

template <typename T> struct wrapper { };

template <typename T>
auto getIds() -> decltype(getIds(wrapper<T>{}))
{
    return getIds(wrapper<T>{});
}

template <typename T>
void getIds(wrapper<T> ) { }

struct MyClass {
    int id;
};

std::vector<decltype(MyClass::id)> getIds(wrapper<MyClass> )
{
    return {1, 2, 3};
}

int main()
{
    for (auto id : getIds<MyClass>()) {
        std::cout << id << " ";
    }

}