2014-01-29 4 views
2

Этот вопрос может существовать, но способ, которым вы называете эту конкретную проблему, является сбивающим с толку.полная специализация метода в шаблоном класса

У меня есть следующий код: первая треть предназначена для файла hpp, вторая третья - в файле impl и последнем бит в cpp. Если я удалю прокомментированный фрагмент кода, он не скомпилируется по причинам, которые я не могу понять.

Почему компилятор не жалуется на другие специализации, которые у меня есть, или, альтернативно, почему он не определяет, что строка 45 является кодом моего кода?

Ошибки:

test.cpp:45:23: error: no function template matches function template specialization 'foo' 
int const A<int,int>::foo(int const & rhs) { 
       ^
test.cpp:58:5: error: call to 'foo' is ambiguous 
    A<int, int>::foo(test_int); 
    ^~~~~~~~~~~~~~~~ 
test.cpp:21:22: note: candidate function 
    static int const foo(int const & rhs); 
       ^
test.cpp:45:23: note: candidate function 
int const A<int,int>::foo(int const & rhs) { 
       ^
2 errors generated. 

Код:

#include <iostream> 

template <typename X, typename Y> 
struct A { 
    static X const foo(Y const & rhs); 
}; 

template <typename X> 
struct A<X,int> { 
    static X const foo(int const & rhs); 
}; 

template <typename Y> 
struct A<int, Y> { 
    static int const foo(Y const & rhs); 
}; 


template <> 
struct A<int,int> { 
    static int const foo(int const & rhs); 
}; 


//---------------------------------------- 

template <typename X, typename Y> 
X const A<X,Y>::foo(Y const & rhs) { 
    X ret; 
    return ret; 
}; 

template <typename X> 
X const A<X,int>::foo(int const & rhs) { 
    X ret; 
    return ret; 
}; 

template <typename Y> 
int const A<int, Y>::foo(Y const & rhs) { 
    return 42; 
}; 

//If I uncomment the following line, the compiler barfs 
//template <> 
int const A<int,int>::foo(int const & rhs) { 
    return rhs; 
}; 




int main() { 
    std::string test_str; 
    int test_int; 
    A<int,std::string>::foo(test_str); 
    A<std::string,int>::foo(test_int); 
    A<std::string,std::string>::foo(test_str); 
    A<int, int>::foo(test_int); 
}; 

ответ

1

Полная специализация не шаблон, а класс. При вводе:

template <> 
int const A<int,int>::foo(int const & rhs) { 
    return rhs; 
}; 

Компилятор видит, что вы хотите специализироваться (template <>) функции-члена шаблона A, который принимает два аргумента. Член, которого вы пытаетесь специализировать, - это специализация шаблона, где оба аргумента: int. Компилятор пытается найти наилучшее совпадение и не может найти его, так как есть два одинаково хороших кандидата: A<X,int> и A<int,Y>, которые могут использовать эту специализацию функции-члена. В этот момент он сдался.

Так что вы хотите, чтобы обеспечить это определение элемента для A<int,int>, и это полная специализация (больше не шаблон), вы должны использовать обычный синтаксис: возвращаемого типа :: члена (арг):

int const A<int,int>::foo(int const & rhs) { 
    return rhs; 
}; 
+0

Означает ли это, что, если бы была только одна частичная специализация шаблона, либо А или А , что шаблон <> работал? Я пробовал комментировать одно из определений, но не работал. Я делаю что-то неправильно? – sajas

+0

@sajas: Это не провалилось бы таким образом ... хотя это, скорее всего, не сделало бы того, что вы хотели. Для объекта типа 'A ' компилятор выберет полную специализацию типа перед частичными специализациями 'A ' или 'A ' (который вы когда-либо оставляли), когда вы вызывали 'foo' на этом объекте, он найти объявление в 'A ' специализация, но не определение. Специализация участника для '(int, int)' в частичной специализации никогда не будет вызвана. –

+0

@sajas: Ваш тест, похоже, терпит неудачу по той же причине, чего я ожидал бы, но я не понимаю, почему проблема возникает в первую очередь. Все еще пытаюсь склонить голову к ответу Дэвида. – stackmate

Смежные вопросы